process.c 21 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118
  1. /* Copyright (c) 1982 Regents of the University of California */
  2. static char sccsid[] = "@(#)process.c 1.12 8/19/83";
  3. /*
  4. * Process management.
  5. *
  6. * This module contains the routines to manage the execution and
  7. * tracing of the debuggee process.
  8. */
  9. #include "defs.h"
  10. #include "process.h"
  11. #include "machine.h"
  12. #include "events.h"
  13. #include "tree.h"
  14. #include "eval.h"
  15. #include "operators.h"
  16. #include "source.h"
  17. #include "object.h"
  18. #include "mappings.h"
  19. #include "main.h"
  20. #include "coredump.h"
  21. #include <signal.h>
  22. #include <errno.h>
  23. #include <sys/param.h>
  24. #include <machine/reg.h>
  25. #include <sys/stat.h>
  26. #ifndef public
  27. typedef struct Process *Process;
  28. Process process;
  29. #define DEFSIG -1
  30. #include "machine.h"
  31. #endif
  32. #define NOTSTARTED 1
  33. #define STOPPED 0177
  34. #define FINISHED 0
  35. /*
  36. * Cache-ing of instruction segment is done to reduce the number
  37. * of system calls.
  38. */
  39. #define CSIZE 1003 /* size of instruction cache */
  40. typedef struct {
  41. Word addr;
  42. Word val;
  43. } CacheWord;
  44. /*
  45. * This structure holds the information we need from the user structure.
  46. */
  47. struct Process {
  48. int pid; /* process being traced */
  49. int mask; /* process status word */
  50. Word reg[NREG]; /* process' registers */
  51. Word oreg[NREG]; /* registers when process last stopped */
  52. short status; /* either STOPPED or FINISHED */
  53. short signo; /* signal that stopped process */
  54. int exitval; /* return value from exit() */
  55. long sigset; /* bit array of traced signals */
  56. CacheWord word[CSIZE]; /* text segment cache */
  57. Ttyinfo ttyinfo; /* process' terminal characteristics */
  58. };
  59. /*
  60. * These definitions are for the arguments to "pio".
  61. */
  62. typedef enum { PREAD, PWRITE } PioOp;
  63. typedef enum { TEXTSEG, DATASEG } PioSeg;
  64. private struct Process pbuf;
  65. #define MAXNCMDARGS 100 /* maximum number of arguments to RUN */
  66. extern int errno;
  67. private Boolean just_started;
  68. private int argc;
  69. private String argv[MAXNCMDARGS];
  70. private String infile, outfile;
  71. /*
  72. * Initialize process information.
  73. */
  74. public process_init()
  75. {
  76. register Integer i;
  77. Char buf[10];
  78. process = &pbuf;
  79. process->status = (coredump) ? STOPPED : NOTSTARTED;
  80. setsigtrace();
  81. for (i = 0; i < NREG; i++) {
  82. sprintf(buf, "$r%d", i);
  83. defregname(identname(buf, false), i);
  84. }
  85. defregname(identname("$ap", true), ARGP);
  86. defregname(identname("$fp", true), FRP);
  87. defregname(identname("$sp", true), STKP);
  88. defregname(identname("$pc", true), PROGCTR);
  89. if (coredump) {
  90. coredump_readin(process->mask, process->reg, process->signo);
  91. pc = process->reg[PROGCTR];
  92. getsrcpos();
  93. }
  94. arginit();
  95. }
  96. /*
  97. * Routines to get at process information from outside this module.
  98. */
  99. public Word reg(n)
  100. Integer n;
  101. {
  102. register Word w;
  103. if (n == NREG) {
  104. w = process->mask;
  105. } else {
  106. w = process->reg[n];
  107. }
  108. return w;
  109. }
  110. public setreg(n, w)
  111. Integer n;
  112. Word w;
  113. {
  114. process->reg[n] = w;
  115. }
  116. /*
  117. * Begin execution.
  118. *
  119. * We set a breakpoint at the end of the code so that the
  120. * process data doesn't disappear after the program terminates.
  121. */
  122. private Boolean remade();
  123. public start(argv, infile, outfile)
  124. String argv[];
  125. String infile, outfile;
  126. {
  127. String pargv[4];
  128. Node cond;
  129. if (coredump) {
  130. coredump = false;
  131. fclose(corefile);
  132. coredump_close();
  133. }
  134. if (argv == nil) {
  135. argv = pargv;
  136. pargv[0] = objname;
  137. pargv[1] = nil;
  138. } else {
  139. argv[argc] = nil;
  140. }
  141. if (remade(objname)) {
  142. reinit(argv, infile, outfile);
  143. }
  144. pstart(process, argv, infile, outfile);
  145. if (process->status == STOPPED) {
  146. pc = 0;
  147. curfunc = program;
  148. if (objsize != 0) {
  149. cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr()));
  150. event_once(cond, buildcmdlist(build(O_ENDX)));
  151. }
  152. }
  153. }
  154. /*
  155. * Check to see if the object file has changed since the symbolic
  156. * information last was read.
  157. */
  158. private time_t modtime;
  159. private Boolean remade(filename)
  160. String filename;
  161. {
  162. struct stat s;
  163. Boolean b;
  164. stat(filename, &s);
  165. b = (Boolean) (modtime != 0 and modtime < s.st_mtime);
  166. modtime = s.st_mtime;
  167. return b;
  168. }
  169. /*
  170. * Set up what signals we want to trace.
  171. */
  172. private setsigtrace()
  173. {
  174. register Integer i;
  175. register Process p;
  176. p = process;
  177. for (i = 1; i <= NSIG; i++) {
  178. psigtrace(p, i, true);
  179. }
  180. psigtrace(p, SIGHUP, false);
  181. psigtrace(p, SIGKILL, false);
  182. psigtrace(p, SIGALRM, false);
  183. psigtrace(p, SIGTSTP, false);
  184. psigtrace(p, SIGCONT, false);
  185. psigtrace(p, SIGCHLD, false);
  186. }
  187. /*
  188. * Initialize the argument list.
  189. */
  190. public arginit()
  191. {
  192. infile = nil;
  193. outfile = nil;
  194. argv[0] = objname;
  195. argc = 1;
  196. }
  197. /*
  198. * Add an argument to the list for the debuggee.
  199. */
  200. public newarg(arg)
  201. String arg;
  202. {
  203. if (argc >= MAXNCMDARGS) {
  204. error("too many arguments");
  205. }
  206. argv[argc++] = arg;
  207. }
  208. /*
  209. * Set the standard input for the debuggee.
  210. */
  211. public inarg(filename)
  212. String filename;
  213. {
  214. if (infile != nil) {
  215. error("multiple input redirects");
  216. }
  217. infile = filename;
  218. }
  219. /*
  220. * Set the standard output for the debuggee.
  221. * Probably should check to avoid overwriting an existing file.
  222. */
  223. public outarg(filename)
  224. String filename;
  225. {
  226. if (outfile != nil) {
  227. error("multiple output redirect");
  228. }
  229. outfile = filename;
  230. }
  231. /*
  232. * Start debuggee executing.
  233. */
  234. public run()
  235. {
  236. process->status = STOPPED;
  237. fixbps();
  238. curline = 0;
  239. start(argv, infile, outfile);
  240. just_started = true;
  241. isstopped = false;
  242. cont(0);
  243. }
  244. /*
  245. * Continue execution wherever we left off.
  246. *
  247. * Note that this routine never returns. Eventually bpact() will fail
  248. * and we'll call printstatus or step will call it.
  249. */
  250. typedef int Intfunc();
  251. private Intfunc *dbintr;
  252. private intr();
  253. #define succeeds == true
  254. #define fails == false
  255. public cont(signo)
  256. int signo;
  257. {
  258. dbintr = signal(SIGINT, intr);
  259. if (just_started) {
  260. just_started = false;
  261. } else {
  262. if (not isstopped) {
  263. error("can't continue execution");
  264. }
  265. isstopped = false;
  266. stepover();
  267. }
  268. for (;;) {
  269. if (single_stepping) {
  270. printnews();
  271. } else {
  272. setallbps();
  273. resume(signo);
  274. unsetallbps();
  275. if (bpact() fails) {
  276. printstatus();
  277. }
  278. }
  279. stepover();
  280. }
  281. /* NOTREACHED */
  282. }
  283. /*
  284. * This routine is called if we get an interrupt while "running" px
  285. * but actually in the debugger. Could happen, for example, while
  286. * processing breakpoints.
  287. *
  288. * We basically just want to keep going; the assumption is
  289. * that when the process resumes it will get the interrupt
  290. * which will then be handled.
  291. */
  292. private intr()
  293. {
  294. signal(SIGINT, intr);
  295. }
  296. public fixintr()
  297. {
  298. signal(SIGINT, dbintr);
  299. }
  300. /*
  301. * Resume execution.
  302. */
  303. public resume(signo)
  304. int signo;
  305. {
  306. register Process p;
  307. p = process;
  308. if (traceexec) {
  309. printf("execution resumes at pc 0x%x\n", process->reg[PROGCTR]);
  310. fflush(stdout);
  311. }
  312. pcont(p, signo);
  313. pc = process->reg[PROGCTR];
  314. if (traceexec) {
  315. printf("execution stops at pc 0x%x on sig %d\n",
  316. process->reg[PROGCTR], p->signo);
  317. fflush(stdout);
  318. }
  319. if (p->status != STOPPED) {
  320. if (p->signo != 0) {
  321. error("program terminated by signal %d", p->signo);
  322. } else if (not runfirst) {
  323. error("program unexpectedly exited with %d", p->exitval);
  324. }
  325. }
  326. }
  327. /*
  328. * Continue execution up to the next source line.
  329. *
  330. * There are two ways to define the next source line depending on what
  331. * is desired when a procedure or function call is encountered. Step
  332. * stops at the beginning of the procedure or call; next skips over it.
  333. */
  334. /*
  335. * Stepc is what is called when the step command is given.
  336. * It has to play with the "isstopped" information.
  337. */
  338. public stepc()
  339. {
  340. if (not isstopped) {
  341. error("can't continue execution");
  342. }
  343. isstopped = false;
  344. dostep(false);
  345. isstopped = true;
  346. }
  347. public next()
  348. {
  349. if (not isstopped) {
  350. error("can't continue execution");
  351. }
  352. isstopped = false;
  353. dostep(true);
  354. isstopped = true;
  355. }
  356. /*
  357. * Single-step over the current machine instruction.
  358. *
  359. * If we're single-stepping by source line we want to step to the
  360. * next source line. Otherwise we're going to continue so there's
  361. * no reason to do all the work necessary to single-step to the next
  362. * source line.
  363. */
  364. private stepover()
  365. {
  366. Boolean b;
  367. if (single_stepping) {
  368. dostep(false);
  369. } else {
  370. b = inst_tracing;
  371. inst_tracing = true;
  372. dostep(false);
  373. inst_tracing = b;
  374. }
  375. }
  376. /*
  377. * Resume execution up to the given address. It is assumed that
  378. * no breakpoints exist between the current address and the one
  379. * we're stepping to. This saves us from setting all the breakpoints.
  380. */
  381. public stepto(addr)
  382. Address addr;
  383. {
  384. setbp(addr);
  385. resume(DEFSIG);
  386. unsetbp(addr);
  387. if (not isbperr()) {
  388. printstatus();
  389. }
  390. }
  391. /*
  392. * Print the status of the process.
  393. * This routine does not return.
  394. */
  395. public printstatus()
  396. {
  397. int status;
  398. if (process->status == FINISHED) {
  399. exit(0);
  400. } else {
  401. curfunc = whatblock(pc);
  402. getsrcpos();
  403. if (process->signo == SIGINT) {
  404. isstopped = true;
  405. printerror();
  406. } else if (isbperr() and isstopped) {
  407. printf("stopped ");
  408. printloc();
  409. putchar('\n');
  410. if (curline > 0) {
  411. printlines(curline, curline);
  412. } else {
  413. printinst(pc, pc);
  414. }
  415. erecover();
  416. } else {
  417. fixbps();
  418. fixintr();
  419. isstopped = true;
  420. printerror();
  421. }
  422. }
  423. }
  424. /*
  425. * Print out the current location in the debuggee.
  426. */
  427. public printloc()
  428. {
  429. printf("in ");
  430. printname(stdout, curfunc);
  431. putchar(' ');
  432. if (curline > 0 and not useInstLoc) {
  433. printsrcpos();
  434. } else {
  435. useInstLoc = false;
  436. curline = 0;
  437. printf("at 0x%x", pc);
  438. }
  439. }
  440. /*
  441. * Some functions for testing the state of the process.
  442. */
  443. public Boolean notstarted(p)
  444. Process p;
  445. {
  446. return (Boolean) (p->status == NOTSTARTED);
  447. }
  448. public Boolean isfinished(p)
  449. Process p;
  450. {
  451. return (Boolean) (p->status == FINISHED);
  452. }
  453. /*
  454. * Return the signal number which stopped the process.
  455. */
  456. public Integer errnum(p)
  457. Process p;
  458. {
  459. return p->signo;
  460. }
  461. /*
  462. * Return the termination code of the process.
  463. */
  464. public Integer exitcode(p)
  465. Process p;
  466. {
  467. return p->exitval;
  468. }
  469. /*
  470. * These routines are used to access the debuggee process from
  471. * outside this module.
  472. *
  473. * They invoke "pio" which eventually leads to a call to "ptrace".
  474. * The system generates an I/O error when a ptrace fails. During reads
  475. * these are ignored, during writes they are reported as an error, and
  476. * for anything else they cause a fatal error.
  477. */
  478. extern Intfunc *onsyserr();
  479. private badaddr;
  480. private read_err(), write_err();
  481. /*
  482. * Read from the process' instruction area.
  483. */
  484. public iread(buff, addr, nbytes)
  485. char *buff;
  486. Address addr;
  487. int nbytes;
  488. {
  489. Intfunc *f;
  490. f = onsyserr(EIO, read_err);
  491. badaddr = addr;
  492. if (coredump) {
  493. coredump_readtext(buff, addr, nbytes);
  494. } else {
  495. pio(process, PREAD, TEXTSEG, buff, addr, nbytes);
  496. }
  497. onsyserr(EIO, f);
  498. }
  499. /*
  500. * Write to the process' instruction area, usually in order to set
  501. * or unset a breakpoint.
  502. */
  503. public iwrite(buff, addr, nbytes)
  504. char *buff;
  505. Address addr;
  506. int nbytes;
  507. {
  508. Intfunc *f;
  509. if (coredump) {
  510. error("no process to write to");
  511. }
  512. f = onsyserr(EIO, write_err);
  513. badaddr = addr;
  514. pio(process, PWRITE, TEXTSEG, buff, addr, nbytes);
  515. onsyserr(EIO, f);
  516. }
  517. /*
  518. * Read for the process' data area.
  519. */
  520. public dread(buff, addr, nbytes)
  521. char *buff;
  522. Address addr;
  523. int nbytes;
  524. {
  525. Intfunc *f;
  526. f = onsyserr(EIO, read_err);
  527. badaddr = addr;
  528. if (coredump) {
  529. coredump_readdata(buff, addr, nbytes);
  530. } else {
  531. pio(process, PREAD, DATASEG, buff, addr, nbytes);
  532. }
  533. onsyserr(EIO, f);
  534. }
  535. /*
  536. * Write to the process' data area.
  537. */
  538. public dwrite(buff, addr, nbytes)
  539. char *buff;
  540. Address addr;
  541. int nbytes;
  542. {
  543. Intfunc *f;
  544. if (coredump) {
  545. error("no process to write to");
  546. }
  547. f = onsyserr(EIO, write_err);
  548. badaddr = addr;
  549. pio(process, PWRITE, DATASEG, buff, addr, nbytes);
  550. onsyserr(EIO, f);
  551. }
  552. /*
  553. * Trap for errors in reading or writing to a process.
  554. * The current approach is to "ignore" read errors and complain
  555. * bitterly about write errors.
  556. */
  557. private read_err()
  558. {
  559. /*
  560. * Ignore.
  561. */
  562. }
  563. private write_err()
  564. {
  565. error("can't write to process (address 0x%x)", badaddr);
  566. }
  567. /*
  568. * Ptrace interface.
  569. */
  570. /*
  571. * This magic macro enables us to look at the process' registers
  572. * in its user structure.
  573. */
  574. #define regloc(reg) (ctob(UPAGES) + ( sizeof(int) * (reg) ))
  575. #define WMASK (~(sizeof(Word) - 1))
  576. #define cachehash(addr) ((unsigned) ((addr >> 2) % CSIZE))
  577. #define FIRSTSIG SIGINT
  578. #define LASTSIG SIGQUIT
  579. #define ischild(pid) ((pid) == 0)
  580. #define traceme() ptrace(0, 0, 0, 0)
  581. #define setrep(n) (1 << ((n)-1))
  582. #define istraced(p) (p->sigset&setrep(p->signo))
  583. /*
  584. * Ptrace options (specified in first argument).
  585. */
  586. #define UREAD 3 /* read from process's user structure */
  587. #define UWRITE 6 /* write to process's user structure */
  588. #define IREAD 1 /* read from process's instruction space */
  589. #define IWRITE 4 /* write to process's instruction space */
  590. #define DREAD 2 /* read from process's data space */
  591. #define DWRITE 5 /* write to process's data space */
  592. #define CONT 7 /* continue stopped process */
  593. #define SSTEP 9 /* continue for approximately one instruction */
  594. #define PKILL 8 /* terminate the process */
  595. /*
  596. * Start up a new process by forking and exec-ing the
  597. * given argument list, returning when the process is loaded
  598. * and ready to execute. The PROCESS information (pointed to
  599. * by the first argument) is appropriately filled.
  600. *
  601. * If the given PROCESS structure is associated with an already running
  602. * process, we terminate it.
  603. */
  604. /* VARARGS2 */
  605. private pstart(p, argv, infile, outfile)
  606. Process p;
  607. String argv[];
  608. String infile;
  609. String outfile;
  610. {
  611. int status;
  612. Fileid in, out;
  613. if (p->pid != 0) { /* child already running? */
  614. ptrace(PKILL, p->pid, 0, 0); /* ... kill it! */
  615. pwait(p->pid, &status); /* wait for it to exit */
  616. unptraced(p->pid);
  617. }
  618. psigtrace(p, SIGTRAP, true);
  619. p->pid = vfork();
  620. if (p->pid == -1) {
  621. panic("can't fork");
  622. }
  623. if (ischild(p->pid)) {
  624. /* setpgrp (p->pid, p->pid); */
  625. traceme();
  626. if (infile != nil) {
  627. in = open(infile, 0);
  628. if (in == -1) {
  629. write(2, "can't read ", 11);
  630. write(2, infile, strlen(infile));
  631. write(2, "\n", 1);
  632. _exit(1);
  633. }
  634. fswap(0, in);
  635. }
  636. if (outfile != nil) {
  637. out = creat(outfile, 0666);
  638. if (out == -1) {
  639. write(2, "can't write ", 12);
  640. write(2, outfile, strlen(outfile));
  641. write(2, "\n", 1);
  642. _exit(1);
  643. }
  644. fswap(1, out);
  645. }
  646. execv(argv[0], argv);
  647. write(2, "can't exec ", 11);
  648. write(2, argv[0], strlen(argv[0]));
  649. write(2, "\n", 1);
  650. _exit(1);
  651. }
  652. pwait(p->pid, &status);
  653. getinfo(p, status);
  654. savetty(stdout, &(p->ttyinfo));
  655. if (p->status != STOPPED) {
  656. error("program could not begin execution");
  657. }
  658. ptraced(p->pid);
  659. }
  660. /*
  661. * Continue a stopped process. The first argument points to a Process
  662. * structure. Before the process is restarted it's user area is modified
  663. * according to the values in the structure. When this routine finishes,
  664. * the structure has the new values from the process's user area.
  665. *
  666. * Pcont terminates when the process stops with a signal pending that
  667. * is being traced (via psigtrace), or when the process terminates.
  668. */
  669. private pcont(p, signo)
  670. Process p;
  671. int signo;
  672. {
  673. int status;
  674. if (p->pid == 0) {
  675. error("program not active");
  676. }
  677. restoretty(stdout, &(p->ttyinfo));
  678. do {
  679. setinfo(p, signo);
  680. sigs_off();
  681. if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) {
  682. panic("error %d trying to continue process", errno);
  683. }
  684. pwait(p->pid, &status);
  685. savetty(stdout, &(p->ttyinfo));
  686. sigs_on();
  687. getinfo(p, status);
  688. } while (p->status == STOPPED and not istraced(p));
  689. }
  690. /*
  691. * Single step as best ptrace can.
  692. */
  693. public pstep(p)
  694. Process p;
  695. {
  696. int status;
  697. setinfo(p, DEFSIG);
  698. sigs_off();
  699. restoretty(stdout, &(p->ttyinfo));
  700. ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo);
  701. pwait(p->pid, &status);
  702. savetty(stdout, &(p->ttyinfo));
  703. sigs_on();
  704. getinfo(p, status);
  705. }
  706. /*
  707. * Return from execution when the given signal is pending.
  708. */
  709. public psigtrace(p, sig, sw)
  710. Process p;
  711. int sig;
  712. Boolean sw;
  713. {
  714. if (sw) {
  715. p->sigset |= setrep(sig);
  716. } else {
  717. p->sigset &= ~setrep(sig);
  718. }
  719. }
  720. /*
  721. * Don't catch any signals.
  722. * Particularly useful when letting a process finish uninhibited.
  723. */
  724. public unsetsigtraces(p)
  725. Process p;
  726. {
  727. p->sigset = 0;
  728. }
  729. /*
  730. * Turn off attention to signals not being caught.
  731. */
  732. private Intfunc *sigfunc[NSIG];
  733. private sigs_off()
  734. {
  735. register int i;
  736. for (i = FIRSTSIG; i < LASTSIG; i++) {
  737. if (i != SIGKILL) {
  738. sigfunc[i] = signal(i, SIG_IGN);
  739. }
  740. }
  741. }
  742. /*
  743. * Turn back on attention to signals.
  744. */
  745. private sigs_on()
  746. {
  747. register int i;
  748. for (i = FIRSTSIG; i < LASTSIG; i++) {
  749. if (i != SIGKILL) {
  750. signal(i, sigfunc[i]);
  751. }
  752. }
  753. }
  754. /*
  755. * Get process information from user area.
  756. */
  757. private int rloc[] ={
  758. R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
  759. };
  760. private getinfo(p, status)
  761. register Process p;
  762. register int status;
  763. {
  764. register int i;
  765. /* ioctl(fileno(stdout), TIOCSPGRP, getpgrp (0)); */
  766. p->signo = (status&0177);
  767. p->exitval = ((status >> 8)&0377);
  768. if (p->signo != STOPPED) {
  769. p->status = FINISHED;
  770. p->pid = 0;
  771. } else {
  772. p->status = p->signo;
  773. p->signo = p->exitval;
  774. p->exitval = 0;
  775. p->mask = ptrace(UREAD, p->pid, regloc(PS), 0);
  776. for (i = 0; i < NREG; i++) {
  777. p->reg[i] = ptrace(UREAD, p->pid, regloc(rloc[i]), 0);
  778. p->oreg[i] = p->reg[i];
  779. }
  780. }
  781. }
  782. /*
  783. * Set process's user area information from given process structure.
  784. */
  785. private setinfo(p, signo)
  786. register Process p;
  787. int signo;
  788. {
  789. register int i;
  790. register int r;
  791. if (signo == DEFSIG) {
  792. if (istraced(p)) {
  793. p->signo = 0;
  794. }
  795. } else {
  796. p->signo = signo;
  797. }
  798. for (i = 0; i < NREG; i++) {
  799. if ((r = p->reg[i]) != p->oreg[i]) {
  800. ptrace(UWRITE, p->pid, regloc(rloc[i]), r);
  801. }
  802. }
  803. /* ioctl(fileno(stdout), TIOCSPGRP, getpgrp (p->pid)); */
  804. }
  805. /*
  806. * Structure for reading and writing by words, but dealing with bytes.
  807. */
  808. typedef union {
  809. Word pword;
  810. Byte pbyte[sizeof(Word)];
  811. } Pword;
  812. /*
  813. * Read (write) from (to) the process' address space.
  814. * We must deal with ptrace's inability to look anywhere other
  815. * than at a word boundary.
  816. */
  817. private Word fetch();
  818. private store();
  819. private pio(p, op, seg, buff, addr, nbytes)
  820. Process p;
  821. PioOp op;
  822. PioSeg seg;
  823. char *buff;
  824. Address addr;
  825. int nbytes;
  826. {
  827. register int i;
  828. register Address newaddr;
  829. register char *cp;
  830. char *bufend;
  831. Pword w;
  832. Address wordaddr;
  833. int byteoff;
  834. if (p->status != STOPPED) {
  835. error("program is not active");
  836. }
  837. cp = buff;
  838. newaddr = addr;
  839. wordaddr = (newaddr&WMASK);
  840. if (wordaddr != newaddr) {
  841. w.pword = fetch(p, seg, wordaddr);
  842. for (i = newaddr - wordaddr; i < sizeof(Word) and nbytes > 0; i++) {
  843. if (op == PREAD) {
  844. *cp++ = w.pbyte[i];
  845. } else {
  846. w.pbyte[i] = *cp++;
  847. }
  848. nbytes--;
  849. }
  850. if (op == PWRITE) {
  851. store(p, seg, wordaddr, w.pword);
  852. }
  853. newaddr = wordaddr + sizeof(Word);
  854. }
  855. byteoff = (nbytes&(~WMASK));
  856. nbytes -= byteoff;
  857. bufend = cp + nbytes;
  858. while (cp < bufend) {
  859. if (op == PREAD) {
  860. *((Word *) cp) = fetch(p, seg, newaddr);
  861. } else {
  862. store(p, seg, newaddr, *((Word *) cp));
  863. }
  864. cp += sizeof(Word);
  865. newaddr += sizeof(Word);
  866. }
  867. if (byteoff > 0) {
  868. w.pword = fetch(p, seg, newaddr);
  869. for (i = 0; i < byteoff; i++) {
  870. if (op == PREAD) {
  871. *cp++ = w.pbyte[i];
  872. } else {
  873. w.pbyte[i] = *cp++;
  874. }
  875. }
  876. if (op == PWRITE) {
  877. store(p, seg, newaddr, w.pword);
  878. }
  879. }
  880. }
  881. /*
  882. * Get a word from a process at the given address.
  883. * The address is assumed to be on a word boundary.
  884. *
  885. * A simple cache scheme is used to avoid redundant ptrace calls
  886. * to the instruction space since it is assumed to be pure.
  887. *
  888. * It is necessary to use a write-through scheme so that
  889. * breakpoints right next to each other don't interfere.
  890. */
  891. private Integer nfetchs, nreads, nwrites;
  892. private Word fetch(p, seg, addr)
  893. Process p;
  894. PioSeg seg;
  895. register int addr;
  896. {
  897. register CacheWord *wp;
  898. register Word w;
  899. switch (seg) {
  900. case TEXTSEG:
  901. ++nfetchs;
  902. wp = &p->word[cachehash(addr)];
  903. if (addr == 0 or wp->addr != addr) {
  904. ++nreads;
  905. w = ptrace(IREAD, p->pid, addr, 0);
  906. wp->addr = addr;
  907. wp->val = w;
  908. } else {
  909. w = wp->val;
  910. }
  911. break;
  912. case DATASEG:
  913. w = ptrace(DREAD, p->pid, addr, 0);
  914. break;
  915. default:
  916. panic("fetch: bad seg %d", seg);
  917. /* NOTREACHED */
  918. }
  919. return w;
  920. }
  921. /*
  922. * Put a word into the process' address space at the given address.
  923. * The address is assumed to be on a word boundary.
  924. */
  925. private store(p, seg, addr, data)
  926. Process p;
  927. PioSeg seg;
  928. int addr;
  929. Word data;
  930. {
  931. register CacheWord *wp;
  932. switch (seg) {
  933. case TEXTSEG:
  934. ++nwrites;
  935. wp = &p->word[cachehash(addr)];
  936. wp->addr = addr;
  937. wp->val = data;
  938. ptrace(IWRITE, p->pid, addr, data);
  939. break;
  940. case DATASEG:
  941. ptrace(DWRITE, p->pid, addr, data);
  942. break;
  943. default:
  944. panic("store: bad seg %d", seg);
  945. /* NOTREACHED */
  946. }
  947. }
  948. public printptraceinfo()
  949. {
  950. printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites);
  951. }
  952. /*
  953. * Swap file numbers so as to redirect standard input and output.
  954. */
  955. private fswap(oldfd, newfd)
  956. int oldfd;
  957. int newfd;
  958. {
  959. if (oldfd != newfd) {
  960. close(oldfd);
  961. dup(newfd);
  962. close(newfd);
  963. }
  964. }