148101Sbostic /*-
2*62135Sbostic  * Copyright (c) 1980, 1993
3*62135Sbostic  *	The Regents of the University of California.  All rights reserved.
448101Sbostic  *
548101Sbostic  * %sccs.include.redist.c%
622369Sdist  */
75487Slinton 
822369Sdist #ifndef lint
9*62135Sbostic static char sccsid[] = "@(#)setbp.c	8.1 (Berkeley) 06/06/93";
1048101Sbostic #endif /* not lint */
1148101Sbostic 
125487Slinton /*
135487Slinton  * Breakpoint/machine interface.
145487Slinton  */
155487Slinton 
165487Slinton #include "defs.h"
175487Slinton #include <signal.h>
185487Slinton #include "machine.h"
195487Slinton #include "process.h"
205487Slinton #include "main.h"
215487Slinton #include "pxops.h"
225487Slinton #include "process/process.rep"
2330845Smckusick #include "process/pxinfo.h"
245487Slinton 
255487Slinton #define BP_OP		O_BPT		/* breakpoint trap */
265487Slinton #define BP_ERRNO	SIGILL		/* signal received at a breakpoint */
275487Slinton 
285487Slinton /*
295487Slinton  * Setting a breakpoint at a location consists of saving
305487Slinton  * the half-word at the location and poking a BP_OP there.
315487Slinton  *
325487Slinton  * We save the locations and half-words on a list for use in unsetting.
335487Slinton  */
345487Slinton 
355487Slinton typedef struct savelist SAVELIST;
365487Slinton 
375487Slinton struct savelist {
385487Slinton 	ADDRESS location;
395487Slinton 	short save;
405487Slinton 	short refcount;
415487Slinton 	SAVELIST *link;
425487Slinton };
435487Slinton 
445487Slinton LOCAL SAVELIST *savelist;
455487Slinton 
465487Slinton /*
475487Slinton  * Set a breakpoint at the given address.  Only save the half-word there
485487Slinton  * if it's not already a breakpoint.
495487Slinton  */
505487Slinton 
setbp(addr)515487Slinton setbp(addr)
525487Slinton ADDRESS addr;
535487Slinton {
5430845Smckusick 	unsigned char w;
555487Slinton 	short save;
565487Slinton 	register SAVELIST *newsave, *s;
575487Slinton 
585487Slinton 	if (option('b')) {
595487Slinton 		printf("setting breakpoint at %d\n", addr);
605487Slinton 		fflush(stdout);
615487Slinton 	}
625487Slinton 	for (s = savelist; s != NIL; s = s->link) {
635487Slinton 		if (s->location == addr) {
645487Slinton 			s->refcount++;
655487Slinton 			return;
665487Slinton 		}
675487Slinton 	}
685487Slinton 	iread(&save, addr, sizeof(save));
695487Slinton 	newsave = alloc(1, SAVELIST);
705487Slinton 	newsave->location = addr;
715487Slinton 	newsave->save = save;
725487Slinton 	newsave->refcount = 1;
735487Slinton 	newsave->link = savelist;
745487Slinton 	savelist = newsave;
755487Slinton 	w = BP_OP;
765487Slinton 	iwrite(&w, addr, sizeof(w));
775487Slinton }
785487Slinton 
795487Slinton /*
805487Slinton  * Unset a breakpoint; unfortunately we have to search the SAVELIST
815487Slinton  * to find the saved value.  The assumption is that the SAVELIST will
825487Slinton  * usually be quite small.
835487Slinton  */
845487Slinton 
unsetbp(addr)855487Slinton unsetbp(addr)
865487Slinton ADDRESS addr;
875487Slinton {
885487Slinton 	register SAVELIST *s, *prev;
895487Slinton 
905487Slinton 	if (option('b')) {
915487Slinton 		printf("unsetting breakpoint at %d\n", addr);
925487Slinton 		fflush(stdout);
935487Slinton 	}
945487Slinton 	prev = NIL;
955487Slinton 	for (s = savelist; s != NIL; s = s->link) {
965487Slinton 		if (s->location == addr) {
975487Slinton 			iwrite(&s->save, addr, sizeof(s->save));
985487Slinton 			s->refcount--;
995487Slinton 			if (s->refcount == 0) {
1005487Slinton 				if (prev == NIL) {
1015487Slinton 					savelist = s->link;
1025487Slinton 				} else {
1035487Slinton 					prev->link = s->link;
1045487Slinton 				}
1055487Slinton 				dispose(s);
1065487Slinton 			}
1075487Slinton 			return;
1085487Slinton 		}
1095487Slinton 		prev = s;
1105487Slinton 	}
1115487Slinton 	panic("unsetbp: couldn't find address %d", addr);
1125487Slinton }
1135487Slinton 
1145487Slinton /*
1155487Slinton  * Predicate to test if the reason the process stopped was because
1165487Slinton  * of a breakpoint.
1175487Slinton  */
1185487Slinton 
isbperr()1195487Slinton BOOLEAN isbperr()
1205487Slinton {
1215487Slinton 	register PROCESS *p;
1225487Slinton 
1235487Slinton 	p = process;
1245487Slinton 	return(p->status==STOPPED && p->signo==BP_ERRNO);
1255487Slinton }
126