1 /*-
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)setbp.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 /*
13  * Breakpoint/machine interface.
14  */
15 
16 #include "defs.h"
17 #include <signal.h>
18 #include "machine.h"
19 #include "process.h"
20 #include "main.h"
21 #include "pxops.h"
22 #include "process/process.rep"
23 #include "process/pxinfo.h"
24 
25 #define BP_OP		O_BPT		/* breakpoint trap */
26 #define BP_ERRNO	SIGILL		/* signal received at a breakpoint */
27 
28 /*
29  * Setting a breakpoint at a location consists of saving
30  * the half-word at the location and poking a BP_OP there.
31  *
32  * We save the locations and half-words on a list for use in unsetting.
33  */
34 
35 typedef struct savelist SAVELIST;
36 
37 struct savelist {
38 	ADDRESS location;
39 	short save;
40 	short refcount;
41 	SAVELIST *link;
42 };
43 
44 LOCAL SAVELIST *savelist;
45 
46 /*
47  * Set a breakpoint at the given address.  Only save the half-word there
48  * if it's not already a breakpoint.
49  */
50 
51 setbp(addr)
52 ADDRESS addr;
53 {
54 	unsigned char w;
55 	short save;
56 	register SAVELIST *newsave, *s;
57 
58 	if (option('b')) {
59 		printf("setting breakpoint at %d\n", addr);
60 		fflush(stdout);
61 	}
62 	for (s = savelist; s != NIL; s = s->link) {
63 		if (s->location == addr) {
64 			s->refcount++;
65 			return;
66 		}
67 	}
68 	iread(&save, addr, sizeof(save));
69 	newsave = alloc(1, SAVELIST);
70 	newsave->location = addr;
71 	newsave->save = save;
72 	newsave->refcount = 1;
73 	newsave->link = savelist;
74 	savelist = newsave;
75 	w = BP_OP;
76 	iwrite(&w, addr, sizeof(w));
77 }
78 
79 /*
80  * Unset a breakpoint; unfortunately we have to search the SAVELIST
81  * to find the saved value.  The assumption is that the SAVELIST will
82  * usually be quite small.
83  */
84 
85 unsetbp(addr)
86 ADDRESS addr;
87 {
88 	register SAVELIST *s, *prev;
89 
90 	if (option('b')) {
91 		printf("unsetting breakpoint at %d\n", addr);
92 		fflush(stdout);
93 	}
94 	prev = NIL;
95 	for (s = savelist; s != NIL; s = s->link) {
96 		if (s->location == addr) {
97 			iwrite(&s->save, addr, sizeof(s->save));
98 			s->refcount--;
99 			if (s->refcount == 0) {
100 				if (prev == NIL) {
101 					savelist = s->link;
102 				} else {
103 					prev->link = s->link;
104 				}
105 				dispose(s);
106 			}
107 			return;
108 		}
109 		prev = s;
110 	}
111 	panic("unsetbp: couldn't find address %d", addr);
112 }
113 
114 /*
115  * Predicate to test if the reason the process stopped was because
116  * of a breakpoint.
117  */
118 
119 BOOLEAN isbperr()
120 {
121 	register PROCESS *p;
122 
123 	p = process;
124 	return(p->status==STOPPED && p->signo==BP_ERRNO);
125 }
126