home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / gdb / remote.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  13.9 KB  |  627 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Van Jacobson and Steven McCanne of Lawrence Berkeley Laboratory.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  *
  36.  * $Header: remote.c,v 1.24 91/03/22 15:35:15 mccanne Exp $;
  37.  */
  38.  
  39. #ifndef lint
  40. static char sccsid[] = "@(#)remote.c    6.5 (Berkeley) 5/8/91";
  41. #endif /* not lint */
  42.  
  43. #include "param.h"
  44.  
  45. #include <stdio.h>
  46. #include <varargs.h>
  47.  
  48. #include <signal.h>
  49. #include <sys/types.h>
  50. #include <sys/ioctl.h>
  51. #include <sys/file.h>
  52.  
  53. #include "defs.h"
  54. #include "frame.h"
  55. #include "inferior.h"
  56. #include "wait.h"
  57.  
  58. #include "kgdb_proto.h"
  59.  
  60. static FILE *kiodebug;
  61. static int icache = 1;
  62. extern int kernel_debugging;
  63.  
  64. static int remote_cache_valid;
  65. static int remote_instub;
  66.  
  67. static void remote_signal();
  68. static void remote_debug();
  69. static void print_msg();
  70.  
  71. static int remote_mtu;
  72. static int (*send_msg)();
  73. static int (*recv_msg)();
  74. static void (*closelink)();
  75.  
  76. static u_char *inbuffer;
  77. static u_char *outbuffer;
  78.  
  79. /*
  80.  * Statistics.
  81.  */
  82. static int remote_ierrs;
  83. static int remote_oerrs;
  84. static int remote_seqerrs;
  85. static int remote_spurious;
  86.  
  87. #define PUTCMD(cmd) m_xchg(cmd, (u_char *)0, 0, (u_char *)0, (int *)0)
  88.  
  89. /*
  90.  * Send an outbound message to the remote machine and read the reply.
  91.  * Either or both message buffers may be NULL.
  92.  */
  93. static int
  94. m_xchg(type, out, outlen, in, inlen)
  95.     int type;
  96.     u_char *out;
  97.     int outlen;
  98.     u_char *in;
  99.     int *inlen;
  100. {
  101.     register int err, (*send)() = send_msg, (*recv)() = recv_msg;
  102.     int ack;
  103.     static int seqbit = 0;
  104.  
  105.     if (!remote_instub) {
  106.         remote_instub = 1;
  107.         PUTCMD(KGDB_EXEC);
  108.     }
  109.  
  110.     seqbit ^= KGDB_SEQ;
  111.     while (1) {
  112.         err = (*send)(type | seqbit, out, outlen);
  113.         if (err) {
  114.             ++remote_oerrs;
  115.             if (kiodebug)
  116.                 remote_debug("send error %d\n", err);
  117.         }
  118.         if (kiodebug)
  119.             print_msg(type | seqbit, out, outlen, 'O');
  120.  
  121.     recv:
  122.         err = (*recv)(&ack, in, inlen);
  123.         if (err) {
  124.             ++remote_ierrs;
  125.             if (kiodebug)
  126.                 remote_debug("recv error %d\n", err);
  127.             remote_cache_valid = 0;
  128.         } else if (kiodebug)
  129.             print_msg(ack, in, inlen ? *inlen : 0, 'I');
  130.  
  131.         if (err)
  132.             continue;
  133.  
  134.         if ((ack & KGDB_ACK) == 0 || KGDB_CMD(ack) != KGDB_CMD(type)) {
  135.             ++remote_spurious;
  136.             continue;
  137.         }
  138.         if ((ack & KGDB_SEQ) ^ seqbit) {
  139.             ++remote_seqerrs;
  140.             goto recv;
  141.         }
  142.         return ack;
  143.     }
  144. }
  145.  
  146. /*
  147.  * Wait for the specified message type.  Discard anything else.
  148.  * (this is used by 'remote-signal' to help us resync with other side.)
  149.  */
  150. static void
  151. m_recv(type, in, inlen)
  152.     int type;
  153.     u_char *in;
  154.     int *inlen;
  155. {
  156.     int reply, err;
  157.  
  158.     while (1) {
  159.         err = (*recv_msg)(&reply, in, inlen);
  160.         if (err) {
  161.             ++remote_ierrs;
  162.             if (kiodebug)
  163.                 remote_debug("recv error %d\n", err);
  164.         } else if (kiodebug)
  165.             print_msg(reply, in, inlen ? *inlen : 0, 'I');
  166.  
  167.         if (KGDB_CMD(reply) == type)
  168.             return;
  169.         ++remote_spurious;
  170.     }
  171. }
  172.  
  173. /*
  174.  * Send a message.  Do not wait for *any* response from the other side.
  175.  * Some other thread of control will pick up the ack that will be generated.
  176.  */
  177. static void
  178. m_send(type, buf, len)
  179.     int type;
  180.     u_char *buf;
  181.     int len;
  182. {
  183.     int err;
  184.  
  185.     if (!remote_instub) {
  186.         remote_instub = 1;
  187.         PUTCMD(KGDB_EXEC);
  188.     }
  189.  
  190.     err = (*send_msg)(type, buf, len);
  191.     if (err) {
  192.         ++remote_ierrs;
  193.         if (kiodebug)
  194.             remote_debug("[send error %d] ", err);
  195.     }
  196.     if (kiodebug)
  197.         print_msg(type, buf, len, 'O');
  198. }
  199.  
  200. /*
  201.  * Open a connection to a remote debugger.  
  202.  * NAME is the filename used for communication.  
  203.  */
  204. void
  205. remote_open(name, from_tty)
  206.     char *name;
  207.     int from_tty;
  208. {
  209.     int bufsize;
  210.  
  211.     remote_debugging = 0;
  212.     if (sl_open(name, &send_msg, &recv_msg, &closelink, &remote_mtu,
  213.             &bufsize))
  214.         return;
  215.     if (from_tty)
  216.         printf("Remote debugging using %s\n", name);
  217.     remote_debugging = 1;
  218.  
  219.     remote_cache_valid = 0;
  220.  
  221.     inbuffer = (u_char *)malloc(bufsize);
  222.     outbuffer = (u_char *)malloc(bufsize);
  223.  
  224.     remote_signal();
  225.  
  226.     remote_ierrs = 0;
  227.     remote_oerrs = 0;
  228.     remote_spurious = 0;
  229. }
  230.  
  231. /*
  232.  * Close the open connection to the remote debugger. Use this when you want
  233.  * to detach and do something else with your gdb.  
  234.  */
  235. void
  236. remote_close(from_tty)
  237.     int from_tty;
  238. {
  239.     if (!remote_debugging)
  240.         error("remote debugging not enabled");
  241.  
  242.     remote_debugging = 0;
  243.     /*
  244.      * Take remote machine out of debug mode.
  245.      */
  246.     (void)PUTCMD(KGDB_KILL);
  247.     (*closelink)();
  248.     if (from_tty)
  249.         printf("Ending remote debugging\n");
  250.  
  251.     free((char *)inbuffer);
  252.     free((char *)outbuffer);
  253. }
  254.  
  255. /*
  256.  * Tell the remote machine to resume.
  257.  */
  258. int
  259. remote_resume(step, signal)
  260.     int step, signal;
  261. {
  262.     if (!step) {
  263.         (void)PUTCMD(KGDB_CONT);
  264.         remote_instub = 0;
  265.     } else {
  266. #ifdef NO_SINGLE_STEP
  267.         single_step(0);
  268. #else
  269.         (void)PUTCMD(KGDB_STEP);
  270. #endif
  271.     }
  272. }
  273.  
  274. /*
  275.  * Wait until the remote machine stops, then return, storing status in STATUS
  276.  * just as `wait' would.
  277.  */
  278. int
  279. remote_wait(status)
  280.     WAITTYPE *status;
  281. {
  282.     int len;
  283.  
  284.     WSETEXIT((*status), 0);
  285.     /*
  286.      * When the machine stops, it will send us a KGDB_SIGNAL message,
  287.      * so we wait for one of these.
  288.      */
  289.     m_recv(KGDB_SIGNAL, inbuffer, &len);
  290.     WSETSTOP((*status), inbuffer[0]);
  291. }
  292.  
  293. /*
  294.  * Register context as of last remote_fetch_registers().
  295.  */
  296. static char reg_cache[REGISTER_BYTES];
  297.  
  298. /*
  299.  * Read the remote registers into the block REGS.
  300.  */
  301. void
  302. remote_fetch_registers(regs)
  303.     char *regs;
  304. {
  305.     int regno, len, rlen, ack;
  306.     u_char *cp, *ep;
  307.  
  308.     regno = -1;
  309.     do {
  310.         outbuffer[0] = regno + 1;
  311.         ack = m_xchg(remote_cache_valid ? 
  312.                      KGDB_REG_R|KGDB_DELTA : KGDB_REG_R,
  313.                  outbuffer, 1, inbuffer, &len);
  314.         cp = inbuffer;
  315.         ep = cp + len;
  316.         while (cp < ep) {
  317.             regno = *cp++;
  318.             rlen = REGISTER_RAW_SIZE(regno);
  319.             bcopy((char *)cp, 
  320.                   ®_cache[REGISTER_BYTE(regno)], rlen);
  321.             cp += rlen;
  322.         }
  323.     } while (ack & KGDB_MORE);
  324.  
  325.     remote_cache_valid = 1;
  326.     bcopy(reg_cache, regs, REGISTER_BYTES);
  327. }
  328.  
  329. /*
  330.  * Store the remote registers from the contents of the block REGS.
  331.  */
  332. void
  333. remote_store_registers(regs)
  334.     char *regs;
  335. {
  336.     u_char *cp, *ep;
  337.     int regno, off, rlen;
  338.  
  339.     cp = outbuffer;
  340.     ep = cp + remote_mtu;
  341.  
  342.     for (regno = 0; regno < NUM_REGS; ++regno) {
  343.         off = REGISTER_BYTE(regno);
  344.         rlen = REGISTER_RAW_SIZE(regno);
  345.         if (!remote_cache_valid ||
  346.             bcmp(®s[off], ®_cache[off], rlen) != 0) {
  347.             if (cp + rlen + 1 >= ep) {
  348.                 (void)m_xchg(KGDB_REG_W, 
  349.                          outbuffer, cp - outbuffer, 
  350.                          (u_char *)0, (int *)0);
  351.                 cp = outbuffer;
  352.             }
  353.             *cp++ = regno;
  354.             bcopy(®s[off], cp, rlen);
  355.             cp += rlen;
  356.         }
  357.     }
  358.     if (cp != outbuffer)
  359.         (void)m_xchg(KGDB_REG_W, outbuffer, cp - outbuffer, 
  360.                  (u_char *)0, (int *)0);
  361.     bcopy(regs, reg_cache, REGISTER_BYTES);
  362. }
  363.  
  364. /*
  365.  * Store a chunk of memory into the remote host.
  366.  * 'remote_addr' is the address in the remote memory space.
  367.  * 'cp' is the address of the buffer in our space, and 'len' is
  368.  * the number of bytes.  Returns an errno status.
  369.  */
  370. int
  371. remote_write_inferior_memory(remote_addr, cp, len)
  372.     CORE_ADDR remote_addr;
  373.     u_char *cp;
  374.     int len;
  375. {
  376.     int cnt;
  377.  
  378.     while (len > 0) {
  379.         cnt = min(len, remote_mtu - 4);
  380.         bcopy((char *)&remote_addr, outbuffer, 4);
  381.         bcopy(cp, outbuffer + 4, cnt);
  382.         (void)m_xchg(KGDB_MEM_W, outbuffer, cnt + 4, inbuffer, &len);
  383.  
  384.         if (inbuffer[0])
  385.             return inbuffer[0];
  386.  
  387.         remote_addr += cnt;
  388.         cp += cnt;
  389.         len -= cnt;
  390.     }
  391.     return 0;
  392. }
  393.  
  394. /*
  395.  * Read memory data directly from the remote machine.
  396.  * 'remote_addr' is the address in the remote memory space.
  397.  * 'cp' is the address of the buffer in our space, and 'len' is
  398.  * the number of bytes.  Returns an errno status.
  399.  */
  400. static int
  401. remote_read_memory(remote_addr, cp, len)
  402.     CORE_ADDR remote_addr;
  403.     u_char *cp;
  404.     int len;
  405. {
  406.     int cnt, inlen;
  407.  
  408.     while (len > 0) {
  409.         cnt = min(len, remote_mtu - 1);
  410.         outbuffer[0] = cnt;
  411.         bcopy((char *)&remote_addr, (char *)&outbuffer[1], 4);
  412.  
  413.         (void)m_xchg(KGDB_MEM_R, outbuffer, 5, inbuffer, &inlen);
  414.  
  415.         if (inbuffer[0] != 0)
  416.             return inbuffer[0];
  417.  
  418.         if (cnt != inlen - 1)
  419.             /* XXX */
  420.             error("remote_read_memory() request botched");
  421.  
  422.         bcopy((char *)&inbuffer[1], (char *)cp, cnt);
  423.  
  424.         remote_addr += cnt;
  425.         cp += cnt;
  426.         len -= cnt;
  427.     }
  428.     return 0;
  429. }
  430.  
  431. int
  432. remote_read_inferior_memory(remote_addr, cp, len)
  433.     CORE_ADDR remote_addr;
  434.     char *cp;
  435.     int len;
  436. {
  437.     int stat = 0;
  438.  
  439.     if (icache) {
  440.         extern CORE_ADDR text_start, text_end;
  441.         CORE_ADDR xferend = remote_addr + len;
  442.  
  443.         if (remote_addr < text_end && text_start < xferend) {
  444.             /*
  445.              * at least part of this xfer is in the text
  446.              * space -- xfer the overlap from the exec file.
  447.              */
  448.             if (remote_addr >= text_start && xferend < text_end)
  449.                 return (xfer_core_file(remote_addr, cp, len));
  450.             if (remote_addr >= text_start) {
  451.                 int i = text_end - remote_addr;
  452.  
  453.                 if (stat = xfer_core_file(remote_addr, cp, i))
  454.                     return (stat);
  455.                 remote_addr += i;
  456.                 cp += i;
  457.                 len -= i;
  458.             } else if (xferend <= text_end) {
  459.                 int i = xferend - text_start;
  460.  
  461.                 len = text_start - remote_addr;
  462.                 if (stat = xfer_core_file(text_start,
  463.                               cp + len, i))
  464.                     return (stat);
  465.             }
  466.         }
  467.     }
  468.     return remote_read_memory(remote_addr, cp, len);
  469. }
  470.  
  471. /*
  472.  * Signal the remote machine.  The remote end might be idle or it might
  473.  * already be in debug mode -- we need to handle both case.  Thus, we use
  474.  * the framing character as the wakeup byte, and send a SIGNAL packet.
  475.  * If the remote host is idle, the framing character will wake it up.
  476.  * If it is in the kgdb stub, then we will get a SIGNAL reply.
  477.  */
  478. static void
  479. remote_signal()
  480. {
  481.     if (!remote_debugging)
  482.         printf("Remote debugging not enabled.\n");
  483.     else {
  484.         remote_instub = 0;
  485.         m_send(KGDB_SIGNAL, (u_char *)0, 0);
  486.     }
  487. }
  488.  
  489. static void
  490. remote_signal_command()
  491. {
  492.     extern int stop_after_attach;
  493.  
  494.     if (!remote_debugging)
  495.         error("Not debugging remote.");
  496.     remote_cache_valid = 0;
  497.     remote_signal();
  498.     restart_remote();
  499. }
  500.  
  501. /*
  502.  * Print a message for debugging.
  503.  */
  504. static void
  505. print_msg(type, buf, len, dir)
  506.     int type;
  507.     u_char *buf;
  508.     int len;
  509.     int dir;
  510. {
  511.     int i;
  512.     char *s;
  513.  
  514.     switch (KGDB_CMD(type)) {
  515.     case KGDB_MEM_R:    s = "memr"; break;
  516.     case KGDB_MEM_W:    s = "memw"; break;
  517.     case KGDB_REG_R:    s = "regr"; break;
  518.     case KGDB_REG_W:    s = "regw"; break;
  519.     case KGDB_CONT:        s = "cont"; break;
  520.     case KGDB_STEP:        s = "step"; break;
  521.     case KGDB_KILL:        s = "kill"; break;
  522.     case KGDB_SIGNAL:    s = "sig "; break;
  523.     case KGDB_EXEC:        s = "exec"; break;
  524.     default:        s = "unk "; break;
  525.     }
  526.     remote_debug("%c %c%c%c%c %s (%02x): ", dir,
  527.              (type & KGDB_ACK) ? 'A' : '.',
  528.              (type & KGDB_DELTA) ? 'D' : '.',
  529.              (type & KGDB_MORE) ? 'M' : '.',
  530.              (type & KGDB_SEQ) ? '-' : '+',
  531.              s, type);
  532.     if (buf)
  533.         for (i = 0; i < len; ++i)
  534.             remote_debug("%02x", buf[i]);
  535.     remote_debug("\n");
  536. }
  537.  
  538. static void
  539. set_remote_text_refs_command(arg, from_tty)
  540.     char *arg;
  541.     int from_tty;
  542. {
  543.     icache = !parse_binary_operation("set remote-text-refs", arg);
  544. }
  545.  
  546. static void
  547. remote_debug_command(arg, from_tty)
  548.     char *arg;
  549.     int from_tty;
  550. {
  551.     char *name;
  552.  
  553.     if (kiodebug != 0 && kiodebug != stderr)
  554.         (void)fclose(kiodebug);
  555.  
  556.     if (arg == 0) {
  557.         kiodebug = 0;
  558.         printf("Remote debugging off.\n");
  559.         return;
  560.     }
  561.     if (arg[0] == '-') {
  562.         kiodebug = stderr;
  563.         name = "stderr";
  564.     } else {
  565.         kiodebug = fopen(arg, "w");
  566.         if (kiodebug == 0) {
  567.             printf("Cannot open '%s'.\n", arg);
  568.             return;
  569.         }
  570.         name = arg;
  571.     }
  572.     printf("Remote debugging output routed to %s.\n", name);
  573. }
  574.  
  575. /* ARGSUSED */
  576. static void
  577. remote_info(arg, from_tty)
  578.     char *arg;
  579.     int from_tty;
  580. {
  581.     printf("Using %s for text references.\n",
  582.         icache? "local executable" : "remote");
  583.     printf("Protocol debugging is %s.\n", kiodebug? "on" : "off");
  584.     printf("%d spurious input messages.\n", remote_spurious);
  585.     printf("%d input errors; %d output errors; %d sequence errors.\n", 
  586.            remote_ierrs, remote_oerrs, remote_seqerrs);
  587. }
  588.  
  589. /* VARARGS */
  590. static void
  591. remote_debug(va_alist)
  592.     va_dcl
  593. {
  594.     register char *cp;
  595.     va_list ap;
  596.  
  597.     va_start(ap);
  598.     cp = va_arg(ap, char *);
  599.     (void)vfprintf(kiodebug, cp, ap);
  600.     va_end(ap);
  601.     fflush(kiodebug);
  602. }
  603.  
  604. extern struct cmd_list_element *setlist;
  605.  
  606. void
  607. _initialize_remote()
  608. {
  609.     add_com("remote-signal", class_run, remote_signal_command,
  610.         "If remote debugging, send interrupt signal to remote.");
  611.     add_cmd("remote-text-refs", class_support, 
  612.         set_remote_text_refs_command,
  613. "Enable/disable use of local executable for text segment references.\n\
  614. If on, all memory read/writes go to remote.\n\
  615. If off, text segment reads use the local executable.",
  616.         &setlist);
  617.  
  618.     add_com("remote-debug", class_run, remote_debug_command,
  619. "With a file name argument, enables output of remote protocol debugging\n\
  620. messages to said file.  If file is `-', stderr is used.\n\
  621. With no argument, remote debugging is disabled.");
  622.  
  623.     add_info("remote", remote_info,
  624.          "Show current settings of remote debugging options.");
  625. }
  626.  
  627.