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