aboutsummaryrefslogtreecommitdiff
path: root/breakpoints.c
diff options
context:
space:
mode:
Diffstat (limited to 'breakpoints.c')
-rw-r--r--breakpoints.c159
1 files changed, 31 insertions, 128 deletions
diff --git a/breakpoints.c b/breakpoints.c
index 9b113a7..73dd638 100644
--- a/breakpoints.c
+++ b/breakpoints.c
@@ -2,10 +2,6 @@
#include "config.h"
#endif
-#include "ltrace.h"
-#include "options.h"
-#include "output.h"
-
#include <stdlib.h>
#include <assert.h>
@@ -13,134 +9,43 @@
#include <sys/ptrace.h>
#endif
-/*****************************************************************************/
-
-/*
- Dictionary code done by Morten Eriksen <mortene@sim.no>.
-
- FIXME: should we merge with dictionary code in demangle.c? 19990704 mortene.
-*/
-
-struct dict_entry {
- struct process * proc;
- struct breakpoint brk; /* addr field of struct is the hash key. */
- struct dict_entry * next;
-};
-
-#define DICTTABLESIZE 997 /* Semi-randomly selected prime number. */
-static struct dict_entry * dict_buckets[DICTTABLESIZE];
-static int dict_initialized = 0;
-
-static void dict_init(void);
-static void dict_clear(void);
-static struct breakpoint * dict_enter(struct process * proc, void * brkaddr);
-struct breakpoint * dict_find_entry(struct process * proc, void * brkaddr);
-static void dict_apply_to_all(void (* func)(struct process *, struct breakpoint *, void * data), void * data);
-
-
-static void
-dict_init(void) {
- int i;
- /* FIXME: is this necessary? Check with ANSI C spec. 19990702 mortene. */
- for (i = 0; i < DICTTABLESIZE; i++) dict_buckets[i] = NULL;
- dict_initialized = 1;
-}
-
-static void
-dict_clear(void) {
- int i;
- struct dict_entry * entry, * nextentry;
-
- for (i = 0; i < DICTTABLESIZE; i++) {
- for (entry = dict_buckets[i]; entry != NULL; entry = nextentry) {
- nextentry = entry->next;
- free(entry);
- }
- dict_buckets[i] = NULL;
- }
-}
-
-static struct breakpoint *
-dict_enter(struct process * proc, void * brkaddr) {
- struct dict_entry * entry, * newentry;
- unsigned int bucketpos = ((unsigned long int)brkaddr) % DICTTABLESIZE;
-
- newentry = malloc(sizeof(struct dict_entry));
- if (!newentry) {
- perror("malloc");
- return NULL;
- }
-
- newentry->proc = proc;
- newentry->brk.addr = brkaddr;
- newentry->brk.enabled = 0;
- newentry->next = NULL;
-
- entry = dict_buckets[bucketpos];
- while (entry && entry->next) entry = entry->next;
-
- if (entry) entry->next = newentry;
- else dict_buckets[bucketpos] = newentry;
-
- if (opt_d > 2)
- output_line(0, "new brk dict entry at %p\n", brkaddr);
-
- return &(newentry->brk);
-}
-
-struct breakpoint *
-dict_find_entry(struct process * proc, void * brkaddr) {
- unsigned int bucketpos = ((unsigned long int)brkaddr) % DICTTABLESIZE;
- struct dict_entry * entry = dict_buckets[bucketpos];
- while (entry) {
- if ((entry->brk.addr == brkaddr) && (entry->proc == proc)) break;
- entry = entry->next;
- }
- return entry ? &(entry->brk) : NULL;
-}
-
-static void
-dict_apply_to_all(void (* func)(struct process *, struct breakpoint *, void * data), void * data) {
- int i;
-
- for (i = 0; i < DICTTABLESIZE; i++) {
- struct dict_entry * entry = dict_buckets[i];
- while (entry) {
- func(entry->proc, &(entry->brk), data);
- entry = entry->next;
- }
- }
-}
-
-#undef DICTTABLESIZE
+#include "ltrace.h"
+#include "options.h"
+#include "debug.h"
+#include "dict.h"
/*****************************************************************************/
struct breakpoint *
address2bpstruct(struct process * proc, void * addr) {
- return dict_find_entry(proc, addr);
+ return dict_find_entry(proc->breakpoints, addr);
}
void
insert_breakpoint(struct process * proc, void * addr) {
struct breakpoint * sbp;
- if (!dict_initialized) {
- dict_init();
- atexit(dict_clear);
+ if (!proc->breakpoints) {
+ proc->breakpoints = dict_init(dict_key2hash_int, dict_key_cmp_int);
+ /* atexit(brk_dict_clear); */ /* why bother to do this on exit? */
+ }
+ sbp = dict_find_entry(proc->breakpoints, addr);
+ if (!sbp) {
+ sbp = malloc(sizeof(struct breakpoint));
+ if (!sbp) {
+ return; /* TODO FIXME XXX: error_mem */
+ }
+ dict_enter(proc->breakpoints, addr, sbp);
+ sbp->addr = addr;
+ sbp->enabled = 0;
}
-
- sbp = dict_find_entry(proc, addr);
- if (!sbp) sbp = dict_enter(proc, addr);
- if (!sbp) return;
-
sbp->enabled++;
if (sbp->enabled==1 && proc->pid) enable_breakpoint(proc->pid, sbp);
}
void
delete_breakpoint(struct process * proc, void * addr) {
- struct breakpoint * sbp = dict_find_entry(proc, addr);
+ struct breakpoint * sbp = dict_find_entry(proc->breakpoints, addr);
assert(sbp); /* FIXME: remove after debugging has been done. */
/* This should only happen on out-of-memory conditions. */
if (sbp == NULL) return;
@@ -151,9 +56,10 @@ delete_breakpoint(struct process * proc, void * addr) {
}
static void
-enable_bp_cb(struct process * proc, struct breakpoint * sbp, void * data) {
- struct process * myproc = (struct process *)data;
- if (myproc == proc && sbp->enabled) enable_breakpoint(proc->pid, sbp);
+enable_bp_cb(void * addr, void * sbp, void * proc) {
+ if (((struct breakpoint *)sbp)->enabled) {
+ enable_breakpoint(((struct process *)proc)->pid, sbp);
+ }
}
void
@@ -174,27 +80,24 @@ enable_all_breakpoints(struct process * proc) {
}
#endif
- if (opt_d>0) {
- output_line(0, "Enabling breakpoints for pid %u...", proc->pid);
- }
- dict_apply_to_all(enable_bp_cb, proc);
+ debug(1, "Enabling breakpoints for pid %u...", proc->pid);
+ dict_apply_to_all(proc->breakpoints, enable_bp_cb, proc);
}
proc->breakpoints_enabled = 1;
}
static void
-disable_bp_cb(struct process * proc, struct breakpoint * sbp, void * data) {
- struct process * myproc = (struct process *)data;
- if (myproc == proc && sbp->enabled) disable_breakpoint(proc->pid, sbp);
+disable_bp_cb(void * addr, void * sbp, void * proc) {
+ if (((struct breakpoint *)sbp)->enabled) {
+ disable_breakpoint(((struct process *)proc)->pid, sbp);
+ }
}
void
disable_all_breakpoints(struct process * proc) {
if (proc->breakpoints_enabled) {
- if (opt_d>0) {
- output_line(0, "Disabling breakpoints for pid %u...", proc->pid);
- }
- dict_apply_to_all(disable_bp_cb, proc);
+ debug(1, "Disabling breakpoints for pid %u...", proc->pid);
+ dict_apply_to_all(proc->breakpoints, disable_bp_cb, proc);
}
proc->breakpoints_enabled = 0;
}