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