⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 remote-fp.c

📁 早期freebsd实现
💻 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 + -