blob: 28bdb4bf817a3e2cf19bb96a80da1d554a6f2aad [file] [log] [blame]
Juan Cespedesd44c6b81998-09-25 14:48:42 +02001#if HAVE_CONFIG_H
2#include "config.h"
3#endif
4
Juan Cespedes5e01f651998-03-08 22:31:44 +01005#include "ltrace.h"
6#include "options.h"
7#include "output.h"
8
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +02009#include <stdlib.h>
10#include <assert.h>
11
12/*****************************************************************************/
13
14/*
15 Dictionary code done by Morten Eriksen <mortene@sim.no>.
16
17 FIXME: should we merge with dictionary code in demangle.c? 19990704 mortene.
18*/
19
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010020struct dict_entry {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020021 struct process * proc;
22 struct breakpoint brk; /* addr field of struct is the hash key. */
23 struct dict_entry * next;
24};
25
26#define DICTTABLESIZE 997 /* Semi-randomly selected prime number. */
27static struct dict_entry * dict_buckets[DICTTABLESIZE];
28static int dict_initialized = 0;
29
30static void dict_init(void);
31static void dict_clear(void);
32static struct breakpoint * dict_enter(struct process * proc, void * brkaddr);
33static struct breakpoint * dict_find_entry(struct process * proc, void * brkaddr);
34static void dict_apply_to_all(void (* func)(struct process *, struct breakpoint *, void * data), void * data);
35
36
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010037static void
38dict_init(void) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020039 int i;
40 /* FIXME: is this necessary? Check with ANSI C spec. 19990702 mortene. */
41 for (i = 0; i < DICTTABLESIZE; i++) dict_buckets[i] = NULL;
42 dict_initialized = 1;
43}
44
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010045static void
46dict_clear(void) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020047 int i;
48 struct dict_entry * entry, * nextentry;
49
50 for (i = 0; i < DICTTABLESIZE; i++) {
51 for (entry = dict_buckets[i]; entry != NULL; entry = nextentry) {
52 nextentry = entry->next;
53 free(entry);
54 }
55 dict_buckets[i] = NULL;
56 }
57}
58
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010059static struct breakpoint *
60dict_enter(struct process * proc, void * brkaddr) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020061 struct dict_entry * entry, * newentry;
62 unsigned int bucketpos = ((unsigned long int)brkaddr) % DICTTABLESIZE;
63
64 newentry = malloc(sizeof(struct dict_entry));
65 if (!newentry) {
66 perror("malloc");
67 return NULL;
68 }
69
70 newentry->proc = proc;
71 newentry->brk.addr = brkaddr;
72 newentry->brk.enabled = 0;
73 newentry->next = NULL;
74
75 entry = dict_buckets[bucketpos];
76 while (entry && entry->next) entry = entry->next;
77
78 if (entry) entry->next = newentry;
79 else dict_buckets[bucketpos] = newentry;
80
81 if (opt_d > 2)
82 output_line(0, "new brk dict entry at %p\n", brkaddr);
83
84 return &(newentry->brk);
85}
86
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010087static struct breakpoint *
88dict_find_entry(struct process * proc, void * brkaddr) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +020089 unsigned int bucketpos = ((unsigned long int)brkaddr) % DICTTABLESIZE;
90 struct dict_entry * entry = dict_buckets[bucketpos];
91 while (entry) {
92 if ((entry->brk.addr == brkaddr) && (entry->proc == proc)) break;
93 entry = entry->next;
94 }
95 return entry ? &(entry->brk) : NULL;
96}
97
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +010098static void
99dict_apply_to_all(void (* func)(struct process *, struct breakpoint *, void * data), void * data) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200100 int i;
101
102 for (i = 0; i < DICTTABLESIZE; i++) {
103 struct dict_entry * entry = dict_buckets[i];
104 while (entry) {
105 func(entry->proc, &(entry->brk), data);
106 entry = entry->next;
107 }
108 }
109}
110
111#undef DICTTABLESIZE
112
113/*****************************************************************************/
114
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100115struct breakpoint *
116address2bpstruct(struct process * proc, void * addr) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200117 return dict_find_entry(proc, addr);
118}
119
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100120void
121insert_breakpoint(struct process * proc, void * addr) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200122 struct breakpoint * sbp;
123
124 if (!dict_initialized) {
125 dict_init();
126 atexit(dict_clear);
127 }
128
129 sbp = dict_find_entry(proc, addr);
130 if (!sbp) sbp = dict_enter(proc, addr);
131 if (!sbp) return;
132
133 sbp->enabled++;
134 if (sbp->enabled==1 && proc->pid) enable_breakpoint(proc->pid, sbp);
135}
136
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100137void
138delete_breakpoint(struct process * proc, void * addr) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200139 struct breakpoint * sbp = dict_find_entry(proc, addr);
140 assert(sbp); /* FIXME: remove after debugging has been done. */
141 /* This should only happen on out-of-memory conditions. */
142 if (sbp == NULL) return;
143
144 sbp->enabled--;
145 if (sbp->enabled == 0) disable_breakpoint(proc->pid, sbp);
146 assert(sbp->enabled >= 0);
147}
148
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100149static void
150enable_bp_cb(struct process * proc, struct breakpoint * sbp, void * data) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200151 struct process * myproc = (struct process *)data;
152 if (myproc == proc && sbp->enabled) enable_breakpoint(proc->pid, sbp);
153}
154
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100155void
156enable_all_breakpoints(struct process * proc) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100157 if (proc->breakpoints_enabled <= 0) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100158 if (opt_d>0) {
159 output_line(0, "Enabling breakpoints for pid %u...", proc->pid);
160 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200161 dict_apply_to_all(enable_bp_cb, proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100162 }
163 proc->breakpoints_enabled = 1;
164}
165
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100166static void
167disable_bp_cb(struct process * proc, struct breakpoint * sbp, void * data) {
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200168 struct process * myproc = (struct process *)data;
169 if (myproc == proc && sbp->enabled) disable_breakpoint(proc->pid, sbp);
170}
171
Juan Cespedes8cc1b9d2002-03-01 19:54:23 +0100172void
173disable_all_breakpoints(struct process * proc) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100174 if (proc->breakpoints_enabled) {
Juan Cespedes5e01f651998-03-08 22:31:44 +0100175 if (opt_d>0) {
176 output_line(0, "Disabling breakpoints for pid %u...", proc->pid);
177 }
Juan Cespedes5b3ffdf2001-07-02 00:52:45 +0200178 dict_apply_to_all(disable_bp_cb, proc);
Juan Cespedes5e01f651998-03-08 22:31:44 +0100179 }
180 proc->breakpoints_enabled = 0;
181}