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