blob: dc2f09e961cd1b845bed1aae042f21f11969e5f1 [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
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010021struct breakpoint *
22address2bpstruct(struct process * proc, void * addr) {
Juan Cespedescac15c32003-01-31 18:58:58 +010023 return dict_find_entry(proc->breakpoints, addr);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020024}
25
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010026void
27insert_breakpoint(struct process * proc, void * addr) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020028 struct breakpoint * sbp;
29
Juan Cespedescac15c32003-01-31 18:58:58 +010030 if (!proc->breakpoints) {
31 proc->breakpoints = dict_init(dict_key2hash_int, dict_key_cmp_int);
32 /* atexit(brk_dict_clear); */ /* why bother to do this on exit? */
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020033 }
Juan Cespedescac15c32003-01-31 18:58:58 +010034 sbp = dict_find_entry(proc->breakpoints, addr);
35 if (!sbp) {
36 sbp = malloc(sizeof(struct breakpoint));
37 if (!sbp) {
38 return; /* TODO FIXME XXX: error_mem */
39 }
40 dict_enter(proc->breakpoints, addr, sbp);
41 sbp->addr = addr;
42 sbp->enabled = 0;
43 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020044 sbp->enabled++;
45 if (sbp->enabled==1 && proc->pid) enable_breakpoint(proc->pid, sbp);
46}
47
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010048void
49delete_breakpoint(struct process * proc, void * addr) {
Juan Cespedescac15c32003-01-31 18:58:58 +010050 struct breakpoint * sbp = dict_find_entry(proc->breakpoints, addr);
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020051 assert(sbp); /* FIXME: remove after debugging has been done. */
52 /* This should only happen on out-of-memory conditions. */
53 if (sbp == NULL) return;
54
55 sbp->enabled--;
56 if (sbp->enabled == 0) disable_breakpoint(proc->pid, sbp);
57 assert(sbp->enabled >= 0);
58}
59
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010060static void
Juan Cespedescac15c32003-01-31 18:58:58 +010061enable_bp_cb(void * addr, void * sbp, void * proc) {
62 if (((struct breakpoint *)sbp)->enabled) {
63 enable_breakpoint(((struct process *)proc)->pid, sbp);
64 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020065}
66
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010067void
68enable_all_breakpoints(struct process * proc) {
Juan Cespedes5e01f651998-03-08 22:31:44 +010069 if (proc->breakpoints_enabled <= 0) {
Juan Cespedesf1bfe202002-03-27 00:22:23 +010070#ifdef __powerpc__
71 unsigned long a;
72
73 /*
74 * PPC HACK! (XXX FIXME TODO)
75 * If the dynamic linker hasn't populated the PLT then
76 * dont enable the breakpoints
77 */
Juan Cespedesde5a7eb2002-03-31 20:53:52 +020078 if (opt_L) {
79 a = ptrace(PTRACE_PEEKTEXT, proc->pid, proc->list_of_symbols->enter_addr, 0);
80 if (a == 0x0)
81 return;
82 }
Juan Cespedesf1bfe202002-03-27 00:22:23 +010083#endif
84
Juan Cespedescac15c32003-01-31 18:58:58 +010085 debug(1, "Enabling breakpoints for pid %u...", proc->pid);
86 dict_apply_to_all(proc->breakpoints, enable_bp_cb, proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +010087 }
88 proc->breakpoints_enabled = 1;
89}
90
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010091static void
Juan Cespedescac15c32003-01-31 18:58:58 +010092disable_bp_cb(void * addr, void * sbp, void * proc) {
93 if (((struct breakpoint *)sbp)->enabled) {
94 disable_breakpoint(((struct process *)proc)->pid, sbp);
95 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020096}
97
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010098void
99disable_all_breakpoints(struct process * proc) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100100 if (proc->breakpoints_enabled) {
Juan Cespedescac15c32003-01-31 18:58:58 +0100101 debug(1, "Disabling breakpoints for pid %u...", proc->pid);
102 dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100103 }
104 proc->breakpoints_enabled = 0;
105}
Juan Cespedes7186e2a2003-01-31 19:56:34 +0100106
107static void
108free_bp_cb(void * addr, void * sbp, void * data) {
109 assert(sbp);
110 free(sbp);
111}
112
113void
114breakpoints_init(struct process * proc) {
115 struct library_symbol * sym;
116
117 if (proc->breakpoints) { /* let's remove that struct */
118 /* TODO FIXME XXX: free() all "struct breakpoint"s */
119 dict_apply_to_all(proc->breakpoints, free_bp_cb, NULL);
120 dict_clear(proc->breakpoints);
121 proc->breakpoints = NULL;
122 }
123
124 if (opt_L && proc->filename) {
125 proc->list_of_symbols = read_elf(proc->filename);
126 if (opt_e) {
127 struct library_symbol ** tmp1 = &(proc->list_of_symbols);
128 while(*tmp1) {
129 struct opt_e_t * tmp2 = opt_e;
130 int keep = !opt_e_enable;
131
132 while(tmp2) {
133 if (!strcmp((*tmp1)->name, tmp2->name)) {
134 keep = opt_e_enable;
135 }
136 tmp2 = tmp2->next;
137 }
138 if (!keep) {
139 *tmp1 = (*tmp1)->next;
140 } else {
141 tmp1 = &((*tmp1)->next);
142 }
143 }
144 }
145 } else {
146 proc->list_of_symbols = NULL;
147 }
148 sym = proc->list_of_symbols;
149 while (sym) {
150 insert_breakpoint(proc, sym->enter_addr); /* proc->pid==0 delays enabling. */
151 sym = sym->next;
152 }
153 proc->callstack_depth = 0;
154 proc->breakpoints_enabled = -1;
155}