📄 remote-fp.c
字号:
/* * Memory-access and commands for remote kbox (Kinetics ethernet/appletalk * bridge), for GDB. Copyright (C) 1988 Free Software Foundation, Inc. * * GDB is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY. No author or distributor accepts responsibility to anyone for * the consequences of using it or for whether it serves any particular * purpose or works at all, unless he says so in writing. Refer to the GDB * General Public License for full details. * * Everyone is granted permission to copy, modify and redistribute GDB, but only * under the conditions described in the GDB General Public License. A copy * of this license is supposed to have been given to you along with GDB so * you can know your rights and responsibilities. It should be in a file * named COPYING. Among other things, the copyright notice and this notice * must be preserved on all copies. * * In other words, go ahead and share GDB, but don't try to stop anyone else * from sharing it farther. Help stamp out software hoarding! *//* * Written by Van Jacobson (van@helios.ee.lbl.gov) * Sat Jan 7 03:42:57 PST 1989: * * This is a first cut at remote debugging suport for a fastpath. All * this version can do is read & write memory in the box. Support * for writing regs or continue/resume really requires support in * the prom ethernet driver or it's too easy to step on yourself. * * To use a version of gdb that contains this code (which we typically * call kbdb for "kbox debugger") do the following: * * kbdb gw.sym (gw.sym is the a.out form of the .srec currently * downloaded into the kbox) * (gdb) attach @foo ("foo" is the host name or ip address of the * kbox you want to debug) * * kbdb will print out a few lines including "Program received signal 5, * Trace/BPT trap" and an address (usually ip4me in gw2.c). The "signal * 5" has to do with fooling gdb into thinking that the attach worked. * Everything else is legit (ie, the registers, stack, etc., should * indicate that you're in the piece of code that processes incoming * "debug" packets. You can now do all the normal gdb things (bt, * print, set, etc.) except set breakpoints or change the execution * path. If you type "return" it will appear to work (but doesn't * really). If you type "continue", you'll get the "Program received * signal 5," again. When you quit, you'll get the usual confirmer: * "The program is running. Quit anyway? (y or n)". Just answer * yes. * * This code will only work with the LBL modified KIP code (it * requires some opcodes we added to the gateway debugging protocol). */#include <stdio.h>#include <signal.h>#include "defs.h"#include "frame.h"#include "inferior.h"#include "remote.h"#include "wait.h"#include <a.out.h>#include <sys/types.h>#include <sys/file.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/time.h>#include <netinet/in.h>#include <strings.h>#include <netdb.h>#include "kgdb_proto.h"/* * KIP fastpath gateway debug protocol */struct gwdb { u_long magic; /* magic number */ u_char op,seq; /* op code, sequence number */ u_short count; /* byte count */ u_long address; /* address of read/write */ u_char data[512];};/* Maximum number of bytes that can be read or written */#define FP_MAXDATA sizeof(((struct gwdb *)0)->data)/* errno byte + data */#define FP_RPCSIZE (1 + FP_MAXDATA)#define gwdbMagic ((u_long)0xFF068020)#define gwdbPort 900 /* udp port number *//* op codes */#define gwdbRead 1#define gwdbWrite 2#define gwdbCall 3#define gwdbStats 4#define gwdbState 5#define gwdbFrame 6int kiodebug;static struct sockaddr_in fsin = { AF_INET }; /* foreign sockaddr_in */static int fsinlen;/* Descriptor for I/O to remote machine. */int fp_desc = -1;static int fp_send(), fp_recv();static void fp_close();static int fp_put(), fp_get();/* * Open a connection to a remote debugger. NAME is the filename used for * communication. */voidfp_open(name, remote_fnp) char *name; struct remote_fn *remote_fnp;{ register u_long iaddr; struct hostent *hp; if (*name >= '0' && *name <= '9' && (iaddr = inet_addr(name)) != -1) { fsin.sin_family = AF_INET; fsin.sin_addr.s_addr = iaddr; } else if (hp = gethostbyname(name)) { fsin.sin_family = hp->h_addrtype; bcopy(hp->h_addr, (caddr_t)&fsin.sin_addr, hp->h_length); } else { error("Bad hostname/ip-address \"%s\"", name); /* NOTREACHED */ } fp_desc = socket(AF_INET, SOCK_DGRAM, 0); if (fp_desc < 0) { perror_with_name(name); /* NOTREACHED */ } fsin.sin_port = gwdbPort; remote_fnp->send = fp_send; remote_fnp->recv = fp_recv; remote_fnp->close = fp_close; remote_fnp->maxdata = FP_MAXDATA; remote_fnp->rpcsize = FP_RPCSIZE;}/* * Close down connection to remote debugger. */static voidfp_close(){ if (fp_desc < 0) printf("fp_close(): fp_desc not open!\n"); else { (void)close(fp_desc); fp_desc = -1; }}static int fp_lasttype;static intfp_send(type, bp, len) register u_char type; register u_char *bp; register int len;{ register int ret; static struct gwdb dbpacket; register struct gwdb *dp = &dbpacket; fp_lasttype = type; switch(KGDB_CMD(type)) { case KGDB_MEM_R: /* Read memory */ if (len != 5) printf("fp_send: MEM_R: bad len (%d != 5)\n", len); dp->magic = gwdbMagic; dp->op = gwdbRead; dp->seq = 1; dp->count = *bp++; bcopy((caddr_t)bp, (caddr_t)&dp->address, sizeof(dp->address)); if (ret = fp_put(dp)) return(ret); break; case KGDB_MEM_W: /* Write memory */ if (len < 5) printf("fp_send: MEM_W: bad len (%d < 5)\n", len); dp->magic = gwdbMagic; dp->op = gwdbWrite; dp->seq = 1; bcopy((caddr_t)bp, (caddr_t)&dp->address, sizeof(dp->address)); bp += sizeof(dp->address); len -= sizeof(dp->address); dp->count = len; bcopy((caddr_t)bp, (caddr_t)dp->data, len); if (ret = fp_put(dp)) return(ret); break; case KGDB_REG_R: /* Read registers */ dp->magic = gwdbMagic; dp->op = gwdbFrame; dp->seq = 1; dp->address = 0; dp->count = REGISTER_BYTES; if (ret = fp_put(dp)) return(ret); break; } return(0);}static intfp_recv(tp, ip, lenp, to) int *tp; register u_char *ip; int *lenp; int to;{ register int type; register int i, ret; static struct gwdb dbpacket; register struct gwdb *dp = &dbpacket; char *fmt = "(fastpath %s not implemented)\n"; if (lenp) *lenp = 0; type = KGDB_CMD(fp_lasttype); *tp = type | (fp_lasttype & KGDB_SEQ) | KGDB_ACK; switch (type) { case KGDB_MEM_R: if (ret = fp_get(dp, to)) return(ret); if (ip) { /* * Build a rpc KGDB_MEM_R reply. This is just * an errno (which is always zero in the case * of a fastpath) and the data. */ ip[0] = 0; bcopy((caddr_t)dp->data, (caddr_t)&ip[1], dp->count); if (lenp) *lenp = dp->count + 1; /* rpc reply size */ } break; case KGDB_MEM_W: if (ret = fp_get(dp, to)) return(ret); break; case KGDB_REG_R: if (ret = fp_get(dp, to)) return(ret); if (ip) { register u_char *bp; bp = dp->data; for (i = 0; i < dp->count / sizeof(int); i++) { *ip++ = i; bcopy((caddr_t)bp, (caddr_t)ip, sizeof(int)); ip += sizeof(int); bp += sizeof(int); } if (lenp) *lenp = i * (sizeof(int) + 1); } break; case KGDB_REG_W: printf(fmt, "REG_W"); break; case KGDB_CONT: /* Next time, respond with a "signal" */ fp_lasttype = KGDB_SIGNAL; printf(fmt, "CONT"); break; case KGDB_STEP: printf(fmt, "STEP"); break; case KGDB_KILL: printf(fmt, "KILL"); break; case KGDB_SIGNAL: printf(fmt, "SIGNAL"); if (ip) { /* Build a fake rpc KGDB_SIGNAL reply */ ip[0] = SIGTRAP; if (lenp) *lenp = 1; } break; case KGDB_EXEC: printf(fmt, "EXEC"); break; default: printf("fp_send(): message type 0x%x unknown\n", fp_lasttype); break; } return(0);}/* * Send the command in BUF to the remote machine, and read the reply into * BUF. Report an error if we get an error reply. */static intfp_put(dp) struct gwdb *dp;{ if (sendto(fp_desc, (caddr_t)dp, sizeof(*dp), 0, (struct sockaddr *)&fsin, sizeof(fsin)) < 0) { perror("fp_put(): sendto"); return(EKGDB_IO); } return(0);}#ifndef FD_SETSIZE /* Gag. */#define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n)))#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n)))#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n)))#define FD_ZERO(p) ((p)->fds_bits[0] = 0)#endifstatic intfp_get(dp, to) struct gwdb *dp; int to;{ register int n; struct timeval timeout; fd_set readfds; /* Wait for data to show up */ timeout.tv_sec = to / 1000; timeout.tv_usec = to % 1000; FD_ZERO(&readfds); FD_SET(fp_desc, &readfds); n = select(fp_desc + 1, &readfds, (fd_set*)0, (fd_set*)0, &timeout); /* XXX should probably check for EINTR */ if (n < 0) { perror("fp_get(): select"); return(EKGDB_IO); } if (n == 0) { fprintf(stderr, "fp_get(): timeout\n"); return(EKGDB_TIMEOUT); } fsinlen = sizeof(fsin); bzero((caddr_t)dp, sizeof(*dp)); n = recvfrom(fp_desc, (caddr_t)dp, sizeof(*dp), 0, (struct sockaddr *)&fsin, &fsinlen); if (n < 0) { perror("fp_get(): recvfrom"); return(EKGDB_IO); } /* Sanity checks */ if (n < sizeof(*dp)) return(EKGDB_RUNT); if (n > sizeof(*dp)) return(EKGDB_2BIG); if (dp->op == 0) return(EKGDB_BADOP); return(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -