📄 remote.c
字号:
/* * Copyright (c) 1990, 1991, 1992 Regents of the University of California. * All rights reserved. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Lawrence Berkeley Laboratory, * Berkeley, CA. The name of the University may not be used to * endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#ifndef lintstatic char rcsid[] = "$Header: remote.c,v 1.3 93/04/26 16:23:50 mccanne Exp $";#endif#include "defs.h"#include <varargs.h>#include <signal.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/file.h>#include "target.h"#include "frame.h"#include "inferior.h"#include "wait.h"#include "gdbcmd.h"#include "remote.h"#include "kgdb_proto.h"extern struct target_ops remote_ops; /* Forward decl */static int remote_debugging;static int remote_quiet;static int to_clamp = 8000;static int to_base = 1000;/* * Eponentially back off a timer value. Clamp the value at to_clamp. */#define BACKOFF(to) ((2 * (to) < to_clamp) ? 2 * (to) : to_clamp)static FILE *kiodebug;static int icache = 1;static int remote_cache_valid;static int remote_instub;static void remote_signal();static void remote_debug();static void print_msg();static struct remote_fn remote_fn;static u_char *inbuffer;static u_char *outbuffer;/* * Statistics. */static int remote_ierrs;static int remote_oerrs;static int remote_seqerrs;static int remote_spurious;#define PUTCMD(cmd) m_xchg(cmd, (u_char *)0, 0, (u_char *)0, (int *)0)/* * Send an outbound message to the remote machine and read the reply. * Either or both message buffers may be NULL. */static intm_xchg(type, out, outlen, in, inlen) int type; u_char *out; int outlen; u_char *in; int *inlen;{ register int err, nrecv; register int (*send)() = remote_fn.send, (*recv)() = remote_fn.recv; int ack; u_long to = to_base; static int seqbit = 0; if (!remote_instub) { remote_instub = 1; (void)PUTCMD(KGDB_EXEC); } seqbit ^= KGDB_SEQ; while (1) { nrecv = 0; err = (*send)(type | seqbit, out, outlen); if (err) { ++remote_oerrs; if (kiodebug) remote_debug("send error %d\n", err); /* XXX shouldn't we retry the !@#$^*ing send? */ } if (kiodebug) print_msg(type | seqbit, out, outlen, 'O'); again: err = (*recv)(&ack, in, inlen, to); if (err != 0) { ++remote_ierrs; if (kiodebug) remote_debug("recv error %d\n", err); remote_cache_valid = 0; if (err == EKGDB_TIMEOUT) { to = BACKOFF(to); if (to >= to_clamp) error("remote host not responding"); continue; } if (++nrecv < 5) /* * Try to receive five times before * retransmitting. */ goto again; continue; } else if (kiodebug) print_msg(ack, in, inlen ? *inlen : 0, 'I'); if ((ack & KGDB_ACK) == 0 || KGDB_CMD(ack) != KGDB_CMD(type)) { ++remote_spurious; continue; } if ((ack & KGDB_SEQ) ^ seqbit) { ++remote_seqerrs; goto again; } return ack; }}/* * Wait for the specified message type. Discard anything else. * (this is used by 'remote-signal' to help us resync with other side.) */static voidm_recv(type, in, inlen) int type; u_char *in; int *inlen;{ int reply, err; while (1) { err = (*remote_fn.recv)(&reply, in, inlen, -1); if (err) { ++remote_ierrs; if (kiodebug) remote_debug("recv error %d\n", err); } else if (kiodebug) print_msg(reply, in, inlen ? *inlen : 0, 'I'); if (KGDB_CMD(reply) == type) return; ++remote_spurious; }}/* * Send a message. Do not wait for *any* response from the other side. * Some other thread of control will pick up the ack that will be generated. */static voidm_send(type, buf, len) int type; u_char *buf; int len;{ int err; if (!remote_instub) { remote_instub = 1; (void)PUTCMD(KGDB_EXEC); } err = (*remote_fn.send)(type, buf, len); if (err) { ++remote_ierrs; if (kiodebug) remote_debug("[send error %d] ", err); } if (kiodebug) print_msg(type, buf, len, 'O');}voidstart_remote(){ init_wait_for_inferior(); remote_go();}voidrestart_remote(){ init_wait_for_inferior_keep_brkpts();#ifdef notdef inferior_pid = 3;#endif remote_go();}static voidremote_bail(arg) void *arg;{ printf("Remote attach interrupted.\n"); remote_quiet = 1; pop_target();}/* * Open a connection to a remote debugger. * NAME is the filename used for communication. */voidremote_open(name, from_tty) char *name; int from_tty;{ extern void sl_open(), fp_open(); void (*func)(); struct cleanup *chain; if (name == 0) error ("\To open a remote debug connection, you need to specify what serial\n\device is attached to the remote system (e.g. /dev/ttya).\"); if (remote_debugging) error("Already remote debugging. Detach first.\n"); target_preopen(from_tty); /* Right now, we only support fastpath and serial debugging */#ifndef NOFASTPATH if (*name == '@') { ++name; func = fp_open; } else#endif func = sl_open; bzero((caddr_t)&remote_fn, sizeof(remote_fn)); (*func)(name, &remote_fn); if (from_tty) printf("Remote debugging using %s\n", name); remote_debugging = 1; remote_cache_valid = 0; /* remote protocol limits max data to one byte */ if (remote_fn.maxdata > 255) remote_fn.maxdata = 255; /* allocate msg buffers */ inbuffer = (u_char *)malloc(remote_fn.rpcsize); outbuffer = (u_char *)malloc(remote_fn.rpcsize); chain = make_cleanup(remote_bail, 0); push_target(&remote_ops); remote_ierrs = 0; remote_oerrs = 0; remote_spurious = 0; /* * XXX * Signal the remote kernel and set things up * so gdb views it as a process. */ remote_signal(); start_remote(); discard_cleanups(chain);}/* * Take the remote kernel out of debugging mode. */voidremote_kill(){ /* XXX * Clear all breakpoints. * It's a very, very bad idea to go away leaving * breakpoints in a remote kernel or to leave it * stopped at a breakpoint. */ clear_breakpoints(); /* * Take remote machine out of debug mode. */ (void)PUTCMD(KGDB_KILL); remote_debugging = 0;}/* * Close the open connection to the remote debugger. Use this when you want * to detach and do something else with your gdb. */voidremote_detach(args, from_tty) char *args; int from_tty;{ if (args) { if (args[0] == 'q') remote_quiet = 1; else error("Bad argument to remote \"detach\"."); } /* this will invoke remote_close() */ pop_target(); if (from_tty) printf("Ending remote debugging.\n");}voidremote_close(quitting) int quitting;{#ifdef notdef if (!remote_debugging) error("Remote debugging not enabled");#endif if (!remote_quiet) { remote_quiet = 0; remote_kill(); } else remote_debugging = 0; (void)(*remote_fn.close)(); free((caddr_t)inbuffer); free((caddr_t)outbuffer);}/* * Tell the remote machine to resume. */voidremote_resume(step, sig) int step, sig;{#ifdef notdef if (sig != 0) error("Cannot signal a remote system");#endif if (!step) { (void)PUTCMD(KGDB_CONT); remote_instub = 0; } else {#ifdef NO_SINGLE_STEP single_step(0);#else (void)PUTCMD(KGDB_STEP);#endif }}/* * Wait until the remote machine stops, then return, storing status in STATUS * just as `wait' would. */intremote_wait(status) WAITTYPE *status;{ int len; WSETEXIT((*status), 0); /* * When the machine stops, it will send us a KGDB_SIGNAL message, * so we wait for one of these. */ m_recv(KGDB_SIGNAL, inbuffer, &len); WSETSTOP((*status), inbuffer[0]); /* * Let the machine dependent module have a chance to * lookup current process context etc. */ set_curproc(); return (0);}/* * Register context as of last remote_fetch_registers(). */static char reg_cache[REGISTER_BYTES];extern char registers[];/* * Read the remote registers into the block REGS. *//* XXX Currently we just read all the registers, so we don't use regno. *//* ARGSUSED */voidremote_fetch_registers(unused_regno)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -