blob: fbeac8115f663fce4ab5a7ac01786108c5e43840 [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +02005#include <stdlib.h>
Juan Cespedes7186e2a2003-01-31 19:56:34 +01006#include <string.h>
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +02007#include <assert.h>
8
Juan Cespedesf1bfe202002-03-27 00:22:23 +01009#ifdef __powerpc__
10#include <sys/ptrace.h>
11#endif
12
Juan Cespedescac15c32003-01-31 18:58:58 +010013#include "ltrace.h"
14#include "options.h"
15#include "debug.h"
16#include "dict.h"
Juan Cespedes7186e2a2003-01-31 19:56:34 +010017#include "elf.h"
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020018
19/*****************************************************************************/
20
Ian Wienand3219f322006-02-16 06:00:00 +010021struct breakpoint *address2bpstruct(struct process *proc, void *addr)
22{
Juan Cespedescac15c32003-01-31 18:58:58 +010023 return dict_find_entry(proc->breakpoints, addr);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020024}
25
Ian Wienand3219f322006-02-16 06:00:00 +010026void insert_breakpoint(struct process *proc, void *addr)
27{
28 struct breakpoint *sbp;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020029
Juan Cespedescac15c32003-01-31 18:58:58 +010030 if (!proc->breakpoints) {
Ian Wienand3219f322006-02-16 06:00:00 +010031 proc->breakpoints =
32 dict_init(dict_key2hash_int, dict_key_cmp_int);
33 /* atexit(brk_dict_clear); *//* why bother to do this on exit? */
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020034 }
Juan Cespedescac15c32003-01-31 18:58:58 +010035 sbp = dict_find_entry(proc->breakpoints, addr);
36 if (!sbp) {
37 sbp = malloc(sizeof(struct breakpoint));
38 if (!sbp) {
Ian Wienand3219f322006-02-16 06:00:00 +010039 return; /* TODO FIXME XXX: error_mem */
Juan Cespedescac15c32003-01-31 18:58:58 +010040 }
41 dict_enter(proc->breakpoints, addr, sbp);
42 sbp->addr = addr;
43 sbp->enabled = 0;
44 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020045 sbp->enabled++;
Ian Wienand3219f322006-02-16 06:00:00 +010046 if (sbp->enabled == 1 && proc->pid)
47 enable_breakpoint(proc->pid, sbp);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020048}
49
Ian Wienand3219f322006-02-16 06:00:00 +010050void delete_breakpoint(struct process *proc, void *addr)
51{
52 struct breakpoint *sbp = dict_find_entry(proc->breakpoints, addr);
53 assert(sbp); /* FIXME: remove after debugging has been done. */
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020054 /* This should only happen on out-of-memory conditions. */
Ian Wienand3219f322006-02-16 06:00:00 +010055 if (sbp == NULL)
56 return;
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020057
58 sbp->enabled--;
Ian Wienand3219f322006-02-16 06:00:00 +010059 if (sbp->enabled == 0)
60 disable_breakpoint(proc->pid, sbp);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020061 assert(sbp->enabled >= 0);
62}
63
Ian Wienand3219f322006-02-16 06:00:00 +010064static void enable_bp_cb(void *addr, void *sbp, void *proc)
65{
Juan Cespedescac15c32003-01-31 18:58:58 +010066 if (((struct breakpoint *)sbp)->enabled) {
67 enable_breakpoint(((struct process *)proc)->pid, sbp);
68 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020069}
70
Ian Wienand3219f322006-02-16 06:00:00 +010071void enable_all_breakpoints(struct process *proc)
72{
Juan Cespedes5e01f651998-03-08 22:31:44 +010073 if (proc->breakpoints_enabled <= 0) {
Juan Cespedesf1bfe202002-03-27 00:22:23 +010074#ifdef __powerpc__
75 unsigned long a;
76
77 /*
78 * PPC HACK! (XXX FIXME TODO)
79 * If the dynamic linker hasn't populated the PLT then
80 * dont enable the breakpoints
81 */
Juan Cespedesde5a7eb2002-03-31 20:53:52 +020082 if (opt_L) {
Ian Wienand3219f322006-02-16 06:00:00 +010083 a = ptrace(PTRACE_PEEKTEXT, proc->pid,
84 proc->list_of_symbols->enter_addr, 0);
Juan Cespedesde5a7eb2002-03-31 20:53:52 +020085 if (a == 0x0)
86 return;
87 }
Juan Cespedesf1bfe202002-03-27 00:22:23 +010088#endif
89
Juan Cespedescac15c32003-01-31 18:58:58 +010090 debug(1, "Enabling breakpoints for pid %u...", proc->pid);
Juan Cespedesa0ccf392003-02-01 19:02:37 +010091 if (proc->breakpoints) {
Ian Wienand3219f322006-02-16 06:00:00 +010092 dict_apply_to_all(proc->breakpoints, enable_bp_cb,
93 proc);
Juan Cespedesa0ccf392003-02-01 19:02:37 +010094 }
Juan Cespedes5e01f651998-03-08 22:31:44 +010095 }
96 proc->breakpoints_enabled = 1;
97}
98
Ian Wienand3219f322006-02-16 06:00:00 +010099static void disable_bp_cb(void *addr, void *sbp, void *proc)
100{
Juan Cespedescac15c32003-01-31 18:58:58 +0100101 if (((struct breakpoint *)sbp)->enabled) {
102 disable_breakpoint(((struct process *)proc)->pid, sbp);
103 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200104}
105
Ian Wienand3219f322006-02-16 06:00:00 +0100106void disable_all_breakpoints(struct process *proc)
107{
Juan Cespedes5e01f651998-03-08 22:31:44 +0100108 if (proc->breakpoints_enabled) {
Juan Cespedescac15c32003-01-31 18:58:58 +0100109 debug(1, "Disabling breakpoints for pid %u...", proc->pid);
110 dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100111 }
112 proc->breakpoints_enabled = 0;
113}
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100114
Ian Wienand3219f322006-02-16 06:00:00 +0100115static void free_bp_cb(void *addr, void *sbp, void *data)
116{
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100117 assert(sbp);
118 free(sbp);
119}
120
Ian Wienand3219f322006-02-16 06:00:00 +0100121void breakpoints_init(struct process *proc)
122{
123 struct library_symbol *sym;
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100124
Ian Wienand3219f322006-02-16 06:00:00 +0100125 if (proc->breakpoints) { /* let's remove that struct */
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100126 /* TODO FIXME XXX: free() all "struct breakpoint"s */
127 dict_apply_to_all(proc->breakpoints, free_bp_cb, NULL);
128 dict_clear(proc->breakpoints);
129 proc->breakpoints = NULL;
130 }
131
132 if (opt_L && proc->filename) {
133 proc->list_of_symbols = read_elf(proc->filename);
134 if (opt_e) {
Ian Wienand3219f322006-02-16 06:00:00 +0100135 struct library_symbol **tmp1 = &(proc->list_of_symbols);
136 while (*tmp1) {
137 struct opt_e_t *tmp2 = opt_e;
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100138 int keep = !opt_e_enable;
139
Ian Wienand3219f322006-02-16 06:00:00 +0100140 while (tmp2) {
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100141 if (!strcmp((*tmp1)->name, tmp2->name)) {
142 keep = opt_e_enable;
143 }
144 tmp2 = tmp2->next;
145 }
146 if (!keep) {
147 *tmp1 = (*tmp1)->next;
148 } else {
149 tmp1 = &((*tmp1)->next);
150 }
151 }
152 }
153 } else {
154 proc->list_of_symbols = NULL;
155 }
156 sym = proc->list_of_symbols;
157 while (sym) {
Ian Wienand3219f322006-02-16 06:00:00 +0100158 insert_breakpoint(proc, sym->enter_addr); /* proc->pid==0 delays enabling. */
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100159 sym = sym->next;
160 }
161 proc->callstack_depth = 0;
162 proc->breakpoints_enabled = -1;
163}