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