Annotation of 43BSDTahoe/ucb/dbx/process.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1983 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)process.c  5.3 (Berkeley) 1/12/88";
                      9: #endif not lint
                     10: 
                     11: static char rcsid[] = "$Header: process.c,v 1.4 88/01/10 00:49:31 donn Exp $";
                     12: 
                     13: /*
                     14:  * Process management.
                     15:  *
                     16:  * This module contains the routines to manage the execution and
                     17:  * tracing of the debuggee process.
                     18:  */
                     19: 
                     20: #include "defs.h"
                     21: #include "process.h"
                     22: #include "machine.h"
                     23: #include "events.h"
                     24: #include "tree.h"
                     25: #include "eval.h"
                     26: #include "operators.h"
                     27: #include "source.h"
                     28: #include "object.h"
                     29: #include "mappings.h"
                     30: #include "main.h"
                     31: #include "coredump.h"
                     32: #include <signal.h>
                     33: #include <errno.h>
                     34: #include <sys/stat.h>
                     35: 
                     36: #ifndef public
                     37: 
                     38: typedef struct Process *Process;
                     39: 
                     40: Process process;
                     41: 
                     42: #define DEFSIG -1
                     43: 
                     44: #include "machine.h"
                     45: 
                     46: #endif
                     47: 
                     48: #define NOTSTARTED 1
                     49: #define STOPPED 0177
                     50: #define FINISHED 0
                     51: 
                     52: /*
                     53:  * A cache of the instruction segment is kept to reduce the number
                     54:  * of system calls.  Might be better just to read the entire
                     55:  * code space into memory.
                     56:  */
                     57: 
                     58: #define CACHESIZE 1003
                     59: 
                     60: typedef struct {
                     61:     Word addr;
                     62:     Word val;
                     63: } CacheWord;
                     64: 
                     65: /*
                     66:  * This structure holds the information we need from the user structure.
                     67:  */
                     68: 
                     69: struct Process {
                     70:     int pid;                   /* process being traced */
                     71:     int mask;                  /* process status word */
                     72:     Word reg[NREG];            /* process' registers */
                     73:     Word oreg[NREG];           /* registers when process last stopped */
                     74:     short status;              /* either STOPPED or FINISHED */
                     75:     short signo;               /* signal that stopped process */
                     76:     short sigcode;             /* extra signal information */
                     77:     int exitval;               /* return value from exit() */
                     78:     long sigset;               /* bit array of traced signals */
                     79:     CacheWord word[CACHESIZE]; /* text segment cache */
                     80:     Ttyinfo ttyinfo;           /* process' terminal characteristics */
                     81:     Address sigstatus;         /* process' handler for current signal */
                     82: };
                     83: 
                     84: /*
                     85:  * These definitions are for the arguments to "pio".
                     86:  */
                     87: 
                     88: typedef enum { PREAD, PWRITE } PioOp;
                     89: typedef enum { TEXTSEG, DATASEG } PioSeg;
                     90: 
                     91: private struct Process pbuf;
                     92: 
                     93: #define MAXNCMDARGS 1000         /* maximum number of arguments to RUN */
                     94: 
                     95: extern int errno;
                     96: 
                     97: private Boolean just_started;
                     98: private int argc;
                     99: private String argv[MAXNCMDARGS];
                    100: private String infile, outfile;
                    101: 
                    102: /*
                    103:  * Initialize process information.
                    104:  */
                    105: 
                    106: public process_init()
                    107: {
                    108:     register integer i;
                    109:     char buf[10];
                    110: 
                    111:     process = &pbuf;
                    112:     process->status = (coredump) ? STOPPED : NOTSTARTED;
                    113:     setsigtrace();
                    114: #   if vax || tahoe
                    115:        for (i = 0; i < NREG; i++) {
                    116:            sprintf(buf, "$r%d", i);
                    117:            defregname(identname(buf, false), i);
                    118:        }
                    119: #      ifdef vax
                    120:            defregname(identname("$ap", true), ARGP);
                    121: #      endif
                    122: #   else
                    123: #       ifdef mc68000
                    124:            for (i = 0; i < 8; i++) {
                    125:                sprintf(buf, "$d%d", i);
                    126:                defregname(identname(buf, false), i);
                    127:                sprintf(buf, "$a%d", i);
                    128:                defregname(identname(buf, false), i + 8);
                    129:            }
                    130: #       endif
                    131: #   endif
                    132:     defregname(identname("$fp", true), FRP);
                    133:     defregname(identname("$sp", true), STKP);
                    134:     defregname(identname("$pc", true), PROGCTR);
                    135:     if (coredump) {
                    136:        coredump_readin(process->mask, process->reg, process->signo);
                    137:        pc = process->reg[PROGCTR];
                    138:     }
                    139:     arginit();
                    140: }
                    141: 
                    142: /*
                    143:  * Routines to get at process information from outside this module.
                    144:  */
                    145: 
                    146: public Word reg(n)
                    147: Integer n;
                    148: {
                    149:     register Word w;
                    150: 
                    151:     if (n == NREG) {
                    152:        w = process->mask;
                    153:     } else {
                    154:        w = process->reg[n];
                    155:     }
                    156:     return w;
                    157: }
                    158: 
                    159: public setreg(n, w)
                    160: Integer n;
                    161: Word w;
                    162: {
                    163:     process->reg[n] = w;
                    164: }
                    165: 
                    166: /*
                    167:  * Begin execution.
                    168:  *
                    169:  * We set a breakpoint at the end of the code so that the
                    170:  * process data doesn't disappear after the program terminates.
                    171:  */
                    172: 
                    173: private Boolean remade();
                    174: 
                    175: public start(argv, infile, outfile)
                    176: String argv[];
                    177: String infile, outfile;
                    178: {
                    179:     String pargv[4];
                    180:     Node cond;
                    181: 
                    182:     if (coredump) {
                    183:        coredump = false;
                    184:        fclose(corefile);
                    185:        coredump_close();
                    186:     }
                    187:     if (argv == nil) {
                    188:        argv = pargv;
                    189:        pargv[0] = objname;
                    190:        pargv[1] = nil;
                    191:     } else {
                    192:        argv[argc] = nil;
                    193:     }
                    194:     pstart(process, argv, infile, outfile);
                    195:     if (remade(objname)) {
                    196:        reinit(argv, infile, outfile);
                    197:     }
                    198:     if (process->status == STOPPED) {
                    199:        pc = CODESTART;
                    200:        setcurfunc(program);
                    201:        if (objsize != 0) {
                    202:            cond = build(O_EQ, build(O_SYM, pcsym), build(O_LCON, lastaddr()));
                    203:            event_once(cond, buildcmdlist(build(O_ENDX)));
                    204:        }
                    205:     }
                    206: }
                    207: 
                    208: /*
                    209:  * Check to see if the object file has changed since the symbolic
                    210:  * information last was read.
                    211:  */
                    212: 
                    213: private time_t modtime;
                    214: 
                    215: private Boolean remade(filename)
                    216: String filename;
                    217: {
                    218:     struct stat s;
                    219:     Boolean b;
                    220: 
                    221:     stat(filename, &s);
                    222:     b = (Boolean) (modtime != 0 and modtime < s.st_mtime);
                    223:     modtime = s.st_mtime;
                    224:     return b;
                    225: }
                    226: 
                    227: /*
                    228:  * Set up what signals we want to trace.
                    229:  */
                    230: 
                    231: private setsigtrace()
                    232: {
                    233:     register Integer i;
                    234:     register Process p;
                    235: 
                    236:     p = process;
                    237:     for (i = 1; i <= NSIG; i++) {
                    238:        psigtrace(p, i, true);
                    239:     }
                    240:     psigtrace(p, SIGHUP, false);
                    241:     psigtrace(p, SIGKILL, false);
                    242:     psigtrace(p, SIGALRM, false);
                    243: #   ifdef SIGTSTP
                    244:        psigtrace(p, SIGTSTP, false);
                    245:        psigtrace(p, SIGCONT, false);
                    246: #   endif
                    247:     psigtrace(p, SIGCHLD, false);
                    248:     psigtrace(p, SIGWINCH, false);
                    249: }
                    250: 
                    251: /*
                    252:  * Initialize the argument list.
                    253:  */
                    254: 
                    255: public arginit()
                    256: {
                    257:     infile = nil;
                    258:     outfile = nil;
                    259:     argv[0] = objname;
                    260:     argc = 1;
                    261: }
                    262: 
                    263: /*
                    264:  * Add an argument to the list for the debuggee.
                    265:  */
                    266: 
                    267: public newarg(arg)
                    268: String arg;
                    269: {
                    270:     if (argc >= MAXNCMDARGS) {
                    271:        error("too many arguments");
                    272:     }
                    273:     argv[argc++] = arg;
                    274: }
                    275: 
                    276: /*
                    277:  * Set the standard input for the debuggee.
                    278:  */
                    279: 
                    280: public inarg(filename)
                    281: String filename;
                    282: {
                    283:     if (infile != nil) {
                    284:        error("multiple input redirects");
                    285:     }
                    286:     infile = filename;
                    287: }
                    288: 
                    289: /*
                    290:  * Set the standard output for the debuggee.
                    291:  * Probably should check to avoid overwriting an existing file.
                    292:  */
                    293: 
                    294: public outarg(filename)
                    295: String filename;
                    296: {
                    297:     if (outfile != nil) {
                    298:        error("multiple output redirect");
                    299:     }
                    300:     outfile = filename;
                    301: }
                    302: 
                    303: /*
                    304:  * Start debuggee executing.
                    305:  */
                    306: 
                    307: public run()
                    308: {
                    309:     process->status = STOPPED;
                    310:     fixbps();
                    311:     curline = 0;
                    312:     start(argv, infile, outfile);
                    313:     just_started = true;
                    314:     isstopped = false;
                    315:     cont(0);
                    316: }
                    317: 
                    318: /*
                    319:  * Continue execution wherever we left off.
                    320:  *
                    321:  * Note that this routine never returns.  Eventually bpact() will fail
                    322:  * and we'll call printstatus or step will call it.
                    323:  */
                    324: 
                    325: typedef int Intfunc();
                    326: 
                    327: private Intfunc *dbintr;
                    328: private intr();
                    329: 
                    330: public cont(signo)
                    331: integer signo;
                    332: {
                    333:     integer s;
                    334: 
                    335:     dbintr = signal(SIGINT, intr);
                    336:     if (just_started) {
                    337:        just_started = false;
                    338:     } else {
                    339:        if (not isstopped) {
                    340:            error("can't continue execution");
                    341:        }
                    342:        isstopped = false;
                    343:        stepover();
                    344:     }
                    345:     s = signo;
                    346:     for (;;) {
                    347:        if (single_stepping) {
                    348:            printnews();
                    349:        } else {
                    350:            setallbps();
                    351:            resume(s);
                    352:            unsetallbps();
                    353:            s = DEFSIG;
                    354:            if (not isbperr() or not bpact()) {
                    355:                printstatus();
                    356:            }
                    357:        }
                    358:        stepover();
                    359:     }
                    360:     /* NOTREACHED */
                    361: }
                    362: 
                    363: /*
                    364:  * This routine is called if we get an interrupt while "running"
                    365:  * but actually in the debugger.  Could happen, for example, while
                    366:  * processing breakpoints.
                    367:  *
                    368:  * We basically just want to keep going; the assumption is
                    369:  * that when the process resumes it will get the interrupt,
                    370:  * which will then be handled.
                    371:  */
                    372: 
                    373: private intr()
                    374: {
                    375:     signal(SIGINT, intr);
                    376: }
                    377: 
                    378: public fixintr()
                    379: {
                    380:     signal(SIGINT, dbintr);
                    381: }
                    382: 
                    383: /*
                    384:  * Resume execution.
                    385:  */
                    386: 
                    387: public resume(signo)
                    388: int signo;
                    389: {
                    390:     register Process p;
                    391: 
                    392:     p = process;
                    393:     pcont(p, signo);
                    394:     pc = process->reg[PROGCTR];
                    395:     if (p->status != STOPPED) {
                    396:        if (p->signo != 0) {
                    397:            error("program terminated by signal %d", p->signo);
                    398:        } else if (not runfirst) {
                    399:            if (p->exitval == 0) {
                    400:                error("program exited");
                    401:            } else {
                    402:                error("program exited with code %d", p->exitval);
                    403:            }
                    404:        }
                    405:     }
                    406: }
                    407: 
                    408: /*
                    409:  * Continue execution up to the next source line.
                    410:  *
                    411:  * There are two ways to define the next source line depending on what
                    412:  * is desired when a procedure or function call is encountered.  Step
                    413:  * stops at the beginning of the procedure or call; next skips over it.
                    414:  */
                    415: 
                    416: /*
                    417:  * Stepc is what is called when the step command is given.
                    418:  * It has to play with the "isstopped" information.
                    419:  */
                    420: 
                    421: public stepc()
                    422: {
                    423:     if (not isstopped) {
                    424:        error("can't continue execution");
                    425:     }
                    426:     isstopped = false;
                    427:     dostep(false);
                    428:     isstopped = true;
                    429: }
                    430: 
                    431: public next()
                    432: {
                    433:     Address oldfrp, newfrp;
                    434: 
                    435:     if (not isstopped) {
                    436:        error("can't continue execution");
                    437:     }
                    438:     isstopped = false;
                    439:     oldfrp = reg(FRP);
                    440:     do {
                    441:        dostep(true);
                    442:        pc = reg(PROGCTR);
                    443:        newfrp = reg(FRP);
                    444:     } while (newfrp < oldfrp and newfrp != 0);
                    445:     isstopped = true;
                    446: }
                    447: 
                    448: /*
                    449:  * Continue execution until the current function returns, or,
                    450:  * if the given argument is non-nil, until execution returns to
                    451:  * somewhere within the given function.
                    452:  */
                    453: 
                    454: public rtnfunc (f)
                    455: Symbol f;
                    456: {
                    457:     Address addr;
                    458:     Symbol t;
                    459: 
                    460:     if (not isstopped) {
                    461:        error("can't continue execution");
                    462:     } else if (f != nil and not isactive(f)) {
                    463:        error("%s is not active", symname(f));
                    464:     } else {
                    465:        addr = return_addr();
                    466:        if (addr == nil) {
                    467:            error("no place to return to");
                    468:        } else {
                    469:            isstopped = false;
                    470:            contto(addr);
                    471:            if (f != nil) {
                    472:                for (;;) {
                    473:                    t = whatblock(pc);
                    474:                    addr = return_addr();
                    475:                if (t == f or addr == nil) break;
                    476:                    contto(addr);
                    477:                }
                    478:            }
                    479:            if (not bpact()) {
                    480:                isstopped = true;
                    481:                printstatus();
                    482:            }
                    483:        }
                    484:     }
                    485: }
                    486: 
                    487: /*
                    488:  * Single-step over the current machine instruction.
                    489:  *
                    490:  * If we're single-stepping by source line we want to step to the
                    491:  * next source line.  Otherwise we're going to continue so there's
                    492:  * no reason to do all the work necessary to single-step to the next
                    493:  * source line.
                    494:  */
                    495: 
                    496: public stepover()
                    497: {
                    498:     Boolean b;
                    499: 
                    500:     if (traceexec) {
                    501:        printf("!! stepping over 0x%x\n", process->reg[PROGCTR]);
                    502:     }
                    503:     if (single_stepping) {
                    504:        dostep(false);
                    505:     } else {
                    506:        b = inst_tracing;
                    507:        inst_tracing = true;
                    508:        dostep(false);
                    509:        inst_tracing = b;
                    510:     }
                    511:     if (traceexec) {
                    512:        printf("!! stepped over to 0x%x\n", process->reg[PROGCTR]);
                    513:     }
                    514: }
                    515: 
                    516: /*
                    517:  * Resume execution up to the given address.  We can either ignore
                    518:  * breakpoints (stepto) or catch them (contto).
                    519:  */
                    520: 
                    521: public stepto(addr)
                    522: Address addr;
                    523: {
                    524:     xto(addr, false);
                    525: }
                    526: 
                    527: private contto (addr)
                    528: Address addr;
                    529: {
                    530:     xto(addr, true);
                    531: }
                    532: 
                    533: private xto (addr, catchbps)
                    534: Address addr;
                    535: boolean catchbps;
                    536: {
                    537:     Address curpc;
                    538: 
                    539:     if (catchbps) {
                    540:        stepover();
                    541:     }
                    542:     curpc = process->reg[PROGCTR];
                    543:     if (addr != curpc) {
                    544:        if (traceexec) {
                    545:            printf("!! stepping from 0x%x to 0x%x\n", curpc, addr);
                    546:        }
                    547:        if (catchbps) {
                    548:            setallbps();
                    549:        }
                    550:        setbp(addr);
                    551:        resume(DEFSIG);
                    552:        unsetbp(addr);
                    553:        if (catchbps) {
                    554:            unsetallbps();
                    555:        }
                    556:        if (not isbperr()) {
                    557:            printstatus();
                    558:        }
                    559:     }
                    560: }
                    561: 
                    562: /*
                    563:  * Print the status of the process.
                    564:  * This routine does not return.
                    565:  */
                    566: 
                    567: public printstatus ()
                    568: {
                    569:     int status;
                    570: 
                    571:     if (process->status == FINISHED) {
                    572:        exit(0);
                    573:     } else {
                    574:        if (runfirst) {
                    575:            fprintf(stderr, "\nEntering debugger ...\n");
                    576:            printheading();
                    577:            init();
                    578:        }
                    579:        setcurfunc(whatblock(pc));
                    580:        getsrcpos();
                    581:        if (process->signo == SIGINT) {
                    582:            isstopped = true;
                    583:            printerror();
                    584:        } else if (isbperr() and isstopped) {
                    585:            printf("stopped ");
                    586:            printloc();
                    587:            putchar('\n');
                    588:            if (curline > 0) {
                    589:                printlines(curline, curline);
                    590:            } else {
                    591:                printinst(pc, pc);
                    592:            }
                    593:            erecover();
                    594:        } else {
                    595:            fixintr();
                    596:            isstopped = true;
                    597:            printerror();
                    598:        }
                    599:     }
                    600: }
                    601: 
                    602: /*
                    603:  * Print out the current location in the debuggee.
                    604:  */
                    605: 
                    606: public printloc()
                    607: {
                    608:     printf("in ");
                    609:     printname(stdout, curfunc);
                    610:     putchar(' ');
                    611:     if (curline > 0 and not useInstLoc) {
                    612:        printsrcpos();
                    613:     } else {
                    614:        useInstLoc = false;
                    615:        curline = 0;
                    616:        printf("at 0x%x", pc);
                    617:     }
                    618: }
                    619: 
                    620: /*
                    621:  * Some functions for testing the state of the process.
                    622:  */
                    623: 
                    624: public Boolean notstarted(p)
                    625: Process p;
                    626: {
                    627:     return (Boolean) (p->status == NOTSTARTED);
                    628: }
                    629: 
                    630: public Boolean isfinished(p)
                    631: Process p;
                    632: {
                    633:     return (Boolean) (p->status == FINISHED);
                    634: }
                    635: 
                    636: /*
                    637:  * Predicate to test if the reason the process stopped was because
                    638:  * of a breakpoint.  If so, as a side effect clear the local copy of
                    639:  * signal handler associated with process.  We must do this so as to
                    640:  * not confuse future stepping or continuing by possibly concluding
                    641:  * the process should continue with a SIGTRAP handler.
                    642:  */
                    643: 
                    644: public boolean isbperr()
                    645: {
                    646:     Process p;
                    647:     boolean b;
                    648: 
                    649:     p = process;
                    650:     if (p->status == STOPPED and p->signo == SIGTRAP) {
                    651:        b = true;
                    652:        p->sigstatus = 0;
                    653:     } else {
                    654:        b = false;
                    655:     }
                    656:     return b;
                    657: }
                    658: 
                    659: /*
                    660:  * Return the signal number that stopped the process.
                    661:  */
                    662: 
                    663: public integer errnum (p)
                    664: Process p;
                    665: {
                    666:     return p->signo;
                    667: }
                    668: 
                    669: /*
                    670:  * Return the signal code associated with the signal.
                    671:  */
                    672: 
                    673: public integer errcode (p)
                    674: Process p;
                    675: {
                    676:     return p->sigcode;
                    677: }
                    678: 
                    679: /*
                    680:  * Return the termination code of the process.
                    681:  */
                    682: 
                    683: public integer exitcode (p)
                    684: Process p;
                    685: {
                    686:     return p->exitval;
                    687: }
                    688: 
                    689: /*
                    690:  * These routines are used to access the debuggee process from
                    691:  * outside this module.
                    692:  *
                    693:  * They invoke "pio" which eventually leads to a call to "ptrace".
                    694:  * The system generates an I/O error when a ptrace fails.  During reads
                    695:  * these are ignored, during writes they are reported as an error, and
                    696:  * for anything else they cause a fatal error.
                    697:  */
                    698: 
                    699: extern Intfunc *onsyserr();
                    700: 
                    701: private badaddr;
                    702: private read_err(), write_err();
                    703: 
                    704: /*
                    705:  * Read from the process' instruction area.
                    706:  */
                    707: 
                    708: public iread(buff, addr, nbytes)
                    709: char *buff;
                    710: Address addr;
                    711: int nbytes;
                    712: {
                    713:     Intfunc *f;
                    714: 
                    715:     f = onsyserr(EIO, read_err);
                    716:     badaddr = addr;
                    717:     if (coredump) {
                    718:        coredump_readtext(buff, addr, nbytes);
                    719:     } else {
                    720:        pio(process, PREAD, TEXTSEG, buff, addr, nbytes);
                    721:     }
                    722:     onsyserr(EIO, f);
                    723: }
                    724: 
                    725: /* 
                    726:  * Write to the process' instruction area, usually in order to set
                    727:  * or unset a breakpoint.
                    728:  */
                    729: 
                    730: public iwrite(buff, addr, nbytes)
                    731: char *buff;
                    732: Address addr;
                    733: int nbytes;
                    734: {
                    735:     Intfunc *f;
                    736: 
                    737:     if (coredump) {
                    738:        error("no process to write to");
                    739:     }
                    740:     f = onsyserr(EIO, write_err);
                    741:     badaddr = addr;
                    742:     pio(process, PWRITE, TEXTSEG, buff, addr, nbytes);
                    743:     onsyserr(EIO, f);
                    744: }
                    745: 
                    746: /*
                    747:  * Read for the process' data area.
                    748:  */
                    749: 
                    750: public dread(buff, addr, nbytes)
                    751: char *buff;
                    752: Address addr;
                    753: int nbytes;
                    754: {
                    755:     Intfunc *f;
                    756: 
                    757:     badaddr = addr;
                    758:     if (coredump) {
                    759:        f = onsyserr(EFAULT, read_err);
                    760:        coredump_readdata(buff, addr, nbytes);
                    761:        onsyserr(EFAULT, f);
                    762:     } else {
                    763:        f = onsyserr(EIO, read_err);
                    764:        pio(process, PREAD, DATASEG, buff, addr, nbytes);
                    765:        onsyserr(EIO, f);
                    766:     }
                    767: }
                    768: 
                    769: /*
                    770:  * Write to the process' data area.
                    771:  */
                    772: 
                    773: public dwrite(buff, addr, nbytes)
                    774: char *buff;
                    775: Address addr;
                    776: int nbytes;
                    777: {
                    778:     Intfunc *f;
                    779: 
                    780:     if (coredump) {
                    781:        error("no process to write to");
                    782:     }
                    783:     f = onsyserr(EIO, write_err);
                    784:     badaddr = addr;
                    785:     pio(process, PWRITE, DATASEG, buff, addr, nbytes);
                    786:     onsyserr(EIO, f);
                    787: }
                    788: 
                    789: /*
                    790:  * Trap for errors in reading or writing to a process.
                    791:  * The current approach is to "ignore" read errors and complain
                    792:  * bitterly about write errors.
                    793:  */
                    794: 
                    795: private read_err()
                    796: {
                    797:     /*
                    798:      * Ignore.
                    799:      */
                    800: }
                    801: 
                    802: private write_err()
                    803: {
                    804:     error("can't write to process (address 0x%x)", badaddr);
                    805: }
                    806: 
                    807: /*
                    808:  * Ptrace interface.
                    809:  */
                    810: 
                    811: #define WMASK           (~(sizeof(Word) - 1))
                    812: #define cachehash(addr) ((unsigned) ((addr >> 2) % CACHESIZE))
                    813: 
                    814: #define FIRSTSIG        SIGINT
                    815: #define LASTSIG         SIGQUIT
                    816: #define ischild(pid)    ((pid) == 0)
                    817: #define traceme()       ptrace(0, 0, 0, 0)
                    818: #define setrep(n)       (1 << ((n)-1))
                    819: #define istraced(p)     (p->sigset&setrep(p->signo))
                    820: 
                    821: /*
                    822:  * Ptrace options (specified in first argument).
                    823:  */
                    824: 
                    825: #define UREAD   3       /* read from process's user structure */
                    826: #define UWRITE  6       /* write to process's user structure */
                    827: #define IREAD   1       /* read from process's instruction space */
                    828: #define IWRITE  4       /* write to process's instruction space */
                    829: #define DREAD   2       /* read from process's data space */
                    830: #define DWRITE  5       /* write to process's data space */
                    831: #define CONT    7       /* continue stopped process */
                    832: #define SSTEP   9       /* continue for approximately one instruction */
                    833: #define PKILL   8       /* terminate the process */
                    834: 
                    835: #ifdef IRIS
                    836: #   define readreg(p, r)       ptrace(10, p->pid, r, 0)
                    837: #   define writereg(p, r, v)   ptrace(11, p->pid, r, v)
                    838: #else
                    839: #   define readreg(p, r)       ptrace(UREAD, p->pid, regloc(r), 0);
                    840: #   define writereg(p, r, v)   ptrace(UWRITE, p->pid, regloc(r), v);
                    841: #endif
                    842: 
                    843: /*
                    844:  * Start up a new process by forking and exec-ing the
                    845:  * given argument list, returning when the process is loaded
                    846:  * and ready to execute.  The PROCESS information (pointed to
                    847:  * by the first argument) is appropriately filled.
                    848:  *
                    849:  * If the given PROCESS structure is associated with an already running
                    850:  * process, we terminate it.
                    851:  */
                    852: 
                    853: /* VARARGS2 */
                    854: private pstart(p, argv, infile, outfile)
                    855: Process p;
                    856: String argv[];
                    857: String infile;
                    858: String outfile;
                    859: {
                    860:     int status;
                    861: 
                    862:     if (p->pid != 0) {
                    863:        pterm(p);
                    864:        cacheflush(p);
                    865:     }
                    866:     fflush(stdout);
                    867:     psigtrace(p, SIGTRAP, true);
                    868: #   ifdef IRIS
                    869:        p->pid = fork();
                    870: #   else
                    871:        p->pid = vfork();
                    872: #   endif
                    873:     if (p->pid == -1) {
                    874:        panic("can't fork");
                    875:     }
                    876:     if (ischild(p->pid)) {
                    877:        nocatcherrs();
                    878:        traceme();
                    879:        if (infile != nil) {
                    880:            infrom(infile);
                    881:        }
                    882:        if (outfile != nil) {
                    883:            outto(outfile);
                    884:        }
                    885:        execv(argv[0], argv);
                    886:        _exit(1);
                    887:     }
                    888:     pwait(p->pid, &status);
                    889:     getinfo(p, status);
                    890:     if (p->status != STOPPED) {
                    891:        beginerrmsg();
                    892:        fprintf(stderr, "warning: cannot execute %s\n", argv[0]);
                    893:     } else {
                    894:        ptraced(p->pid);
                    895:     }
                    896: }
                    897: 
                    898: /*
                    899:  * Terminate a ptrace'd process.
                    900:  */
                    901: 
                    902: public pterm (p)
                    903: Process p;
                    904: {
                    905:     integer status;
                    906: 
                    907:     if (p != nil and p->pid != 0) {
                    908:        ptrace(PKILL, p->pid, 0, 0);
                    909:        pwait(p->pid, &status);
                    910:        unptraced(p->pid);
                    911:     }
                    912: }
                    913: 
                    914: /*
                    915:  * Continue a stopped process.  The first argument points to a Process
                    916:  * structure.  Before the process is restarted it's user area is modified
                    917:  * according to the values in the structure.  When this routine finishes,
                    918:  * the structure has the new values from the process's user area.
                    919:  *
                    920:  * Pcont terminates when the process stops with a signal pending that
                    921:  * is being traced (via psigtrace), or when the process terminates.
                    922:  */
                    923: 
                    924: private pcont(p, signo)
                    925: Process p;
                    926: int signo;
                    927: {
                    928:     int s, status;
                    929: 
                    930:     if (p->pid == 0) {
                    931:        error("program is not active");
                    932:     }
                    933:     s = signo;
                    934:     do {
                    935:        setinfo(p, s);
                    936:        if (traceexec) {
                    937:            printf("!! pcont from 0x%x with signal %d (%d)\n",
                    938:                p->reg[PROGCTR], s, p->signo);
                    939:            fflush(stdout);
                    940:        }
                    941:        sigs_off();
                    942:        if (ptrace(CONT, p->pid, p->reg[PROGCTR], p->signo) < 0) {
                    943:            panic("error %d trying to continue process", errno);
                    944:        }
                    945:        pwait(p->pid, &status);
                    946:        sigs_on();
                    947:        getinfo(p, status);
                    948:        if (p->status == STOPPED and traceexec and not istraced(p)) {
                    949:            printf("!! ignored signal %d at 0x%x\n",
                    950:                p->signo, p->reg[PROGCTR]);
                    951:            fflush(stdout);
                    952:        }
                    953:        s = p->signo;
                    954:     } while (p->status == STOPPED and not istraced(p));
                    955:     if (traceexec) {
                    956:        printf("!! pcont to 0x%x on signal %d\n", p->reg[PROGCTR], p->signo);
                    957:        fflush(stdout);
                    958:     }
                    959: }
                    960: 
                    961: /*
                    962:  * Single step as best ptrace can.
                    963:  */
                    964: 
                    965: public pstep(p, signo)
                    966: Process p;
                    967: integer signo;
                    968: {
                    969:     int s, status;
                    970: 
                    971:     s = signo;
                    972:     do {
                    973:        setinfo(p, s);
                    974:        if (traceexec) {
                    975:            printf("!! pstep from 0x%x with signal %d (%d)\n",
                    976:                p->reg[PROGCTR], s, p->signo);
                    977:            fflush(stdout);
                    978:        }
                    979:        sigs_off();
                    980:        if (ptrace(SSTEP, p->pid, p->reg[PROGCTR], p->signo) < 0) {
                    981:            panic("error %d trying to step process", errno);
                    982:        }
                    983:        pwait(p->pid, &status);
                    984:        sigs_on();
                    985:        getinfo(p, status);
                    986: #      if mc68000 || m68000
                    987:            if (p->status == STOPPED and p->signo == SIGTRAP) {
                    988:                p->reg[PROGCTR] += 2;
                    989:            }
                    990: #      endif
                    991:        if (p->status == STOPPED and traceexec and not istraced(p)) {
                    992:            printf("!! pstep ignored signal %d at 0x%x\n",
                    993:                p->signo, p->reg[PROGCTR]);
                    994:            fflush(stdout);
                    995:        }
                    996:        s = p->signo;
                    997:     } while (p->status == STOPPED and not istraced(p));
                    998:     if (traceexec) {
                    999:        printf("!! pstep to 0x%x on signal %d\n",
                   1000:            p->reg[PROGCTR], p->signo);
                   1001:        fflush(stdout);
                   1002:     }
                   1003:     if (p->status != STOPPED) {
                   1004:        if (p->exitval == 0) {
                   1005:            error("program exited\n");
                   1006:        } else {
                   1007:            error("program exited with code %d\n", p->exitval);
                   1008:        }
                   1009:     }
                   1010: }
                   1011: 
                   1012: /*
                   1013:  * Return from execution when the given signal is pending.
                   1014:  */
                   1015: 
                   1016: public psigtrace(p, sig, sw)
                   1017: Process p;
                   1018: int sig;
                   1019: Boolean sw;
                   1020: {
                   1021:     if (sw) {
                   1022:        p->sigset |= setrep(sig);
                   1023:     } else {
                   1024:        p->sigset &= ~setrep(sig);
                   1025:     }
                   1026: }
                   1027: 
                   1028: /*
                   1029:  * Don't catch any signals.
                   1030:  * Particularly useful when letting a process finish uninhibited.
                   1031:  */
                   1032: 
                   1033: public unsetsigtraces(p)
                   1034: Process p;
                   1035: {
                   1036:     p->sigset = 0;
                   1037: }
                   1038: 
                   1039: /*
                   1040:  * Turn off attention to signals not being caught.
                   1041:  */
                   1042: 
                   1043: private Intfunc *sigfunc[NSIG];
                   1044: 
                   1045: private sigs_off()
                   1046: {
                   1047:     register int i;
                   1048: 
                   1049:     for (i = FIRSTSIG; i < LASTSIG; i++) {
                   1050:        if (i != SIGKILL) {
                   1051:            sigfunc[i] = signal(i, SIG_IGN);
                   1052:        }
                   1053:     }
                   1054: }
                   1055: 
                   1056: /*
                   1057:  * Turn back on attention to signals.
                   1058:  */
                   1059: 
                   1060: private sigs_on()
                   1061: {
                   1062:     register int i;
                   1063: 
                   1064:     for (i = FIRSTSIG; i < LASTSIG; i++) {
                   1065:        if (i != SIGKILL) {
                   1066:            signal(i, sigfunc[i]);
                   1067:        }
                   1068:     }
                   1069: }
                   1070: 
                   1071: /*
                   1072:  * Get process information from user area.
                   1073:  */
                   1074: 
                   1075: private getinfo (p, status)
                   1076: register Process p;
                   1077: register int status;
                   1078: {
                   1079:     register int i;
                   1080:     Address addr;
                   1081: 
                   1082:     p->signo = (status&0177);
                   1083:     p->exitval = ((status >> 8)&0377);
                   1084:     if (p->signo != STOPPED) {
                   1085:        p->status = FINISHED;
                   1086:        p->pid = 0;
                   1087:        p->reg[PROGCTR] = 0;
                   1088:     } else {
                   1089:        p->status = p->signo;
                   1090:        p->signo = p->exitval;
                   1091:        p->exitval = 0;
                   1092: #       ifdef IRIS
                   1093:            p->mask = readreg(p, RPS);
                   1094: #       else
                   1095:            p->sigcode = ptrace(UREAD, p->pid, &((struct user *)0)->u_code, 0);
                   1096:            p->mask = readreg(p, PS);
                   1097: #       endif
                   1098:        for (i = 0; i < NREG; i++) {
                   1099:            p->reg[i] = readreg(p, rloc[i]);
                   1100:            p->oreg[i] = p->reg[i];
                   1101:        }
                   1102: #       ifdef mc68000
                   1103:            if (p->status == STOPPED and p->signo == SIGTRAP and
                   1104:                p->reg[PROGCTR] > CODESTART
                   1105:            ) {
                   1106:                p->reg[PROGCTR] -= 2;
                   1107:            }
                   1108: #       endif
                   1109:        savetty(stdout, &(p->ttyinfo));
                   1110:        addr = (Address) &(((struct user *) 0)->u_signal[p->signo]);
                   1111:        p->sigstatus = (Address) ptrace(UREAD, p->pid, addr, 0);
                   1112:     }
                   1113: }
                   1114: 
                   1115: /*
                   1116:  * Set process's user area information from given process structure.
                   1117:  */
                   1118: 
                   1119: private setinfo (p, signo)
                   1120: register Process p;
                   1121: int signo;
                   1122: {
                   1123:     register int i;
                   1124:     register int r;
                   1125: 
                   1126:     if (signo == DEFSIG) {
                   1127:        if (istraced(p) and (p->sigstatus == 0 or p->sigstatus == 1)) {
                   1128:            p->signo = 0;
                   1129:        }
                   1130:     } else {
                   1131:        p->signo = signo;
                   1132:     }
                   1133:     for (i = 0; i < NREG; i++) {
                   1134:        if ((r = p->reg[i]) != p->oreg[i]) {
                   1135:            writereg(p, rloc[i], r);
                   1136:        }
                   1137:     }
                   1138:     restoretty(stdout, &(p->ttyinfo));
                   1139: }
                   1140: 
                   1141: /*
                   1142:  * Return the address associated with the current signal.
                   1143:  * (Plus two since the address points to the beginning of a procedure).
                   1144:  */
                   1145: 
                   1146: public Address usignal (p)
                   1147: Process p;
                   1148: {
                   1149:     Address r;
                   1150: 
                   1151:     r = p->sigstatus;
                   1152:     if (r != 0 and r != 1) {
                   1153:        r += FUNCOFFSET;
                   1154:     }
                   1155:     return r;
                   1156: }
                   1157: 
                   1158: /*
                   1159:  * Structure for reading and writing by words, but dealing with bytes.
                   1160:  */
                   1161: 
                   1162: typedef union {
                   1163:     Word pword;
                   1164:     Byte pbyte[sizeof(Word)];
                   1165: } Pword;
                   1166: 
                   1167: /*
                   1168:  * Read (write) from (to) the process' address space.
                   1169:  * We must deal with ptrace's inability to look anywhere other
                   1170:  * than at a word boundary.
                   1171:  */
                   1172: 
                   1173: private Word fetch();
                   1174: private store();
                   1175: 
                   1176: private pio(p, op, seg, buff, addr, nbytes)
                   1177: Process p;
                   1178: PioOp op;
                   1179: PioSeg seg;
                   1180: char *buff;
                   1181: Address addr;
                   1182: int nbytes;
                   1183: {
                   1184:     register int i;
                   1185:     register Address newaddr;
                   1186:     register char *cp;
                   1187:     char *bufend;
                   1188:     Pword w;
                   1189:     Address wordaddr;
                   1190:     int byteoff;
                   1191: 
                   1192:     if (p->status != STOPPED) {
                   1193:        error("program is not active");
                   1194:     }
                   1195:     cp = buff;
                   1196:     newaddr = addr;
                   1197:     wordaddr = (newaddr&WMASK);
                   1198:     if (wordaddr != newaddr) {
                   1199:        w.pword = fetch(p, seg, wordaddr);
                   1200:        for (i = newaddr - wordaddr; i < sizeof(Word) and nbytes > 0; i++) {
                   1201:            if (op == PREAD) {
                   1202:                *cp++ = w.pbyte[i];
                   1203:            } else {
                   1204:                w.pbyte[i] = *cp++;
                   1205:            }
                   1206:            nbytes--;
                   1207:        }
                   1208:        if (op == PWRITE) {
                   1209:            store(p, seg, wordaddr, w.pword);
                   1210:        }
                   1211:        newaddr = wordaddr + sizeof(Word);
                   1212:     }
                   1213:     byteoff = (nbytes&(~WMASK));
                   1214:     nbytes -= byteoff;
                   1215:     bufend = cp + nbytes;
                   1216: #ifdef tahoe
                   1217:     if (((int)cp)&WMASK) {
                   1218:        /*
                   1219:         * Must copy a byte at a time, buffer not word addressable.
                   1220:         */
                   1221:        while (cp < bufend) {
                   1222:            if (op == PREAD) {
                   1223:                w.pword = fetch(p, seg, newaddr);
                   1224:                for (i = 0; i < sizeof(Word); i++)
                   1225:                    *cp++ = w.pbyte[i];
                   1226:            } else {
                   1227:                for (i = 0; i < sizeof(Word); i++)
                   1228:                    w.pbyte[i] = *cp++;
                   1229:                store(p, seg, newaddr, w.pword);
                   1230:            }
                   1231:            newaddr += sizeof(Word);
                   1232:        }
                   1233:     } else {
                   1234:     /*
                   1235:      * Buffer, word aligned, act normally...
                   1236:      */
                   1237: #endif
                   1238:     while (cp < bufend) {
                   1239:        if (op == PREAD) {
                   1240:            *((Word *) cp) = fetch(p, seg, newaddr);
                   1241:        } else {
                   1242:            store(p, seg, newaddr, *((Word *) cp));
                   1243:        }
                   1244:        cp += sizeof(Word);
                   1245:        newaddr += sizeof(Word);
                   1246:     }
                   1247: #ifdef tahoe
                   1248:     }
                   1249: #endif
                   1250:     if (byteoff > 0) {
                   1251:        w.pword = fetch(p, seg, newaddr);
                   1252:        for (i = 0; i < byteoff; i++) {
                   1253:            if (op == PREAD) {
                   1254:                *cp++ = w.pbyte[i];
                   1255:            } else {
                   1256:                w.pbyte[i] = *cp++;
                   1257:            }
                   1258:        }
                   1259:        if (op == PWRITE) {
                   1260:            store(p, seg, newaddr, w.pword);
                   1261:        }
                   1262:     }
                   1263: }
                   1264: 
                   1265: /*
                   1266:  * Get a word from a process at the given address.
                   1267:  * The address is assumed to be on a word boundary.
                   1268:  *
                   1269:  * A simple cache scheme is used to avoid redundant ptrace calls
                   1270:  * to the instruction space since it is assumed to be pure.
                   1271:  *
                   1272:  * It is necessary to use a write-through scheme so that
                   1273:  * breakpoints right next to each other don't interfere.
                   1274:  */
                   1275: 
                   1276: private Integer nfetchs, nreads, nwrites;
                   1277: 
                   1278: private Word fetch(p, seg, addr)
                   1279: Process p;
                   1280: PioSeg seg;
                   1281: register int addr;
                   1282: {
                   1283:     register CacheWord *wp;
                   1284:     register Word w;
                   1285: 
                   1286:     switch (seg) {
                   1287:        case TEXTSEG:
                   1288:            ++nfetchs;
                   1289:            wp = &p->word[cachehash(addr)];
                   1290:            if (addr == 0 or wp->addr != addr) {
                   1291:                ++nreads;
                   1292:                w = ptrace(IREAD, p->pid, addr, 0);
                   1293:                wp->addr = addr;
                   1294:                wp->val = w;
                   1295:            } else {
                   1296:                w = wp->val;
                   1297:            }
                   1298:            break;
                   1299: 
                   1300:        case DATASEG:
                   1301:            w = ptrace(DREAD, p->pid, addr, 0);
                   1302:            break;
                   1303: 
                   1304:        default:
                   1305:            panic("fetch: bad seg %d", seg);
                   1306:            /* NOTREACHED */
                   1307:     }
                   1308:     return w;
                   1309: }
                   1310: 
                   1311: /*
                   1312:  * Put a word into the process' address space at the given address.
                   1313:  * The address is assumed to be on a word boundary.
                   1314:  */
                   1315: 
                   1316: private store(p, seg, addr, data)
                   1317: Process p;
                   1318: PioSeg seg;
                   1319: int addr;
                   1320: Word data;
                   1321: {
                   1322:     register CacheWord *wp;
                   1323: 
                   1324:     switch (seg) {
                   1325:        case TEXTSEG:
                   1326:            ++nwrites;
                   1327:            wp = &p->word[cachehash(addr)];
                   1328:            wp->addr = addr;
                   1329:            wp->val = data;
                   1330:            ptrace(IWRITE, p->pid, addr, data);
                   1331:            break;
                   1332: 
                   1333:        case DATASEG:
                   1334:            ptrace(DWRITE, p->pid, addr, data);
                   1335:            break;
                   1336: 
                   1337:        default:
                   1338:            panic("store: bad seg %d", seg);
                   1339:            /* NOTREACHED */
                   1340:     }
                   1341: }
                   1342: 
                   1343: /*
                   1344:  * Flush the instruction cache associated with a process.
                   1345:  */
                   1346: 
                   1347: private cacheflush (p)
                   1348: Process p;
                   1349: {
                   1350:     bzero(p->word, sizeof(p->word));
                   1351: }
                   1352: 
                   1353: public printptraceinfo()
                   1354: {
                   1355:     printf("%d fetchs, %d reads, %d writes\n", nfetchs, nreads, nwrites);
                   1356: }
                   1357: 
                   1358: /*
                   1359:  * Redirect input.
                   1360:  * Assuming this is called from a child, we should be careful to avoid
                   1361:  * (possibly) shared standard I/O buffers.
                   1362:  */
                   1363: 
                   1364: private infrom (filename)
                   1365: String filename;
                   1366: {
                   1367:     Fileid in;
                   1368: 
                   1369:     in = open(filename, 0);
                   1370:     if (in == -1) {
                   1371:        write(2, "can't read ", 11);
                   1372:        write(2, filename, strlen(filename));
                   1373:        write(2, "\n", 1);
                   1374:        _exit(1);
                   1375:     }
                   1376:     fswap(0, in);
                   1377: }
                   1378: 
                   1379: /*
                   1380:  * Redirect standard output.
                   1381:  * Same assumptions as for "infrom" above.
                   1382:  */
                   1383: 
                   1384: private outto (filename)
                   1385: String filename;
                   1386: {
                   1387:     Fileid out;
                   1388: 
                   1389:     out = creat(filename, 0666);
                   1390:     if (out == -1) {
                   1391:        write(2, "can't write ", 12);
                   1392:        write(2, filename, strlen(filename));
                   1393:        write(2, "\n", 1);
                   1394:        _exit(1);
                   1395:     }
                   1396:     fswap(1, out);
                   1397: }
                   1398: 
                   1399: /*
                   1400:  * Swap file numbers, useful for redirecting standard input or output.
                   1401:  */
                   1402: 
                   1403: private fswap(oldfd, newfd)
                   1404: Fileid oldfd;
                   1405: Fileid newfd;
                   1406: {
                   1407:     if (oldfd != newfd) {
                   1408:        close(oldfd);
                   1409:        dup(newfd);
                   1410:        close(newfd);
                   1411:     }
                   1412: }
                   1413: 
                   1414: /*
                   1415:  * Signal name manipulation.
                   1416:  */
                   1417: 
                   1418: private String signames[NSIG] = {
                   1419:     0,
                   1420:     "HUP", "INT", "QUIT", "ILL", "TRAP",
                   1421:     "IOT", "EMT", "FPE", "KILL", "BUS",
                   1422:     "SEGV", "SYS", "PIPE", "ALRM", "TERM",
                   1423:     0, "STOP", "TSTP", "CONT", "CHLD",
                   1424:     "TTIN", "TTOU", "TINT", "XCPU", "XFSZ",
                   1425:     "VTALRM", "PROF", "WINCH", "USR1", "USR2"
                   1426: };
                   1427: 
                   1428: /*
                   1429:  * Get the signal number associated with a given name.
                   1430:  * The name is first translated to upper case if necessary.
                   1431:  */
                   1432: 
                   1433: public integer siglookup (s)
                   1434: String s;
                   1435: {
                   1436:     register char *p, *q;
                   1437:     char buf[100];
                   1438:     integer i;
                   1439: 
                   1440:     p = s;
                   1441:     q = buf;
                   1442:     while (*p != '\0') {
                   1443:        if (*p >= 'a' and *p <= 'z') {
                   1444:            *q = (*p - 'a') + 'A';
                   1445:        } else {
                   1446:            *q = *p;
                   1447:        }
                   1448:        ++p;
                   1449:        ++q;
                   1450:     }
                   1451:     *q = '\0';
                   1452:     p = buf;
                   1453:     if (buf[0] == 'S' and buf[1] == 'I' and buf[2] == 'G') {
                   1454:        p += 3;
                   1455:     }
                   1456:     i = 1;
                   1457:     for (;;) {
                   1458:        if (i >= sizeof(signames) div sizeof(signames[0])) {
                   1459:            error("signal \"%s\" unknown", s);
                   1460:            i = 0;
                   1461:            break;
                   1462:        }
                   1463:        if (signames[i] != nil and streq(signames[i], p)) {
                   1464:            break;
                   1465:        }
                   1466:        ++i;
                   1467:     }
                   1468:     return i;
                   1469: }
                   1470: 
                   1471: /*
                   1472:  * Print all signals being ignored by the debugger.
                   1473:  * These signals are auotmatically
                   1474:  * passed on to the debugged process.
                   1475:  */
                   1476: 
                   1477: public printsigsignored (p)
                   1478: Process p;
                   1479: {
                   1480:     printsigs(~p->sigset);
                   1481: }
                   1482: 
                   1483: /*
                   1484:  * Print all signals being intercepted by
                   1485:  * the debugger for the specified process.
                   1486:  */
                   1487: 
                   1488: public printsigscaught(p)
                   1489: Process p;
                   1490: {
                   1491:     printsigs(p->sigset);
                   1492: }
                   1493: 
                   1494: private printsigs (set)
                   1495: integer set;
                   1496: {
                   1497:     integer s;
                   1498:     char separator[2];
                   1499: 
                   1500:     separator[0] = '\0';
                   1501:     for (s = 1; s < sizeof(signames) div sizeof(signames[0]); s++) {
                   1502:        if (set & setrep(s)) {
                   1503:            if (signames[s] != nil) {
                   1504:                printf("%s%s", separator, signames[s]);
                   1505:                separator[0] = ' ';
                   1506:                separator[1] = '\0';
                   1507:            }
                   1508:        }
                   1509:     }
                   1510:     if (separator[0] == ' ') {
                   1511:        putchar('\n');
                   1512:     }
                   1513: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.