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