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