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

📄 gdb-stub.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
static void single_step(struct gdb_regs *regs){	union mips_instruction insn;	unsigned int targ;	int is_branch, is_cond, i;	targ = regs->cp0_epc;	insn.word = *(unsigned int *)targ;	is_branch = is_cond = 0;	switch (insn.i_format.opcode) {	/*	 * jr and jalr are in r_format format.	 */	case spec_op:		switch (insn.r_format.func) {		case jalr_op:		case jr_op:			targ = *(&regs->reg0 + insn.r_format.rs);			is_branch = 1;			break;		}		break;	/*	 * This group contains:	 * bltz_op, bgez_op, bltzl_op, bgezl_op,	 * bltzal_op, bgezal_op, bltzall_op, bgezall_op.	 */	case bcond_op:		is_branch = is_cond = 1;		targ += 4 + (insn.i_format.simmediate << 2);		break;	/*	 * These are unconditional and in j_format.	 */	case jal_op:	case j_op:		is_branch = 1;		targ += 4;		targ >>= 28;		targ <<= 28;		targ |= (insn.j_format.target << 2);		break;	/*	 * These are conditional.	 */	case beq_op:	case beql_op:	case bne_op:	case bnel_op:	case blez_op:	case blezl_op:	case bgtz_op:	case bgtzl_op:	case cop0_op:	case cop1_op:	case cop2_op:	case cop1x_op:		is_branch = is_cond = 1;		targ += 4 + (insn.i_format.simmediate << 2);		break;	}					if (is_branch) {		i = 0;		if (is_cond && targ != (regs->cp0_epc + 8)) {			step_bp[i].addr = regs->cp0_epc + 8;			step_bp[i++].val = *(unsigned *)(regs->cp0_epc + 8);			*(unsigned *)(regs->cp0_epc + 8) = BP;		}		step_bp[i].addr = targ;		step_bp[i].val  = *(unsigned *)targ;		*(unsigned *)targ = BP;	} else {		step_bp[0].addr = regs->cp0_epc + 4;		step_bp[0].val  = *(unsigned *)(regs->cp0_epc + 4);		*(unsigned *)(regs->cp0_epc + 4) = BP;	}}/* *  If asynchronously interrupted by gdb, then we need to set a breakpoint *  at the interrupted instruction so that we wind up stopped with a  *  reasonable stack frame. */static struct gdb_bp_save async_bp;void set_async_breakpoint(unsigned int epc){	async_bp.addr = epc;	async_bp.val  = *(unsigned *)epc;	*(unsigned *)epc = BP;	flush_cache_all();}/* * This function does all command processing for interfacing to gdb.  It * returns 1 if you should skip the instruction at the trap address, 0 * otherwise. */void handle_exception (struct gdb_regs *regs){	int trap;			/* Trap type */	int sigval;	int addr;	int length;	char *ptr;	unsigned long *stack;#if 0		printk("in handle_exception()\n");	show_gdbregs(regs);#endif		/*	 * First check trap type. If this is CPU_UNUSABLE and CPU_ID is 1,	 * the simply switch the FPU on and return since this is no error	 * condition. kernel/traps.c does the same.	 * FIXME: This doesn't work yet, so we don't catch CPU_UNUSABLE	 * traps for now.	 */	trap = (regs->cp0_cause & 0x7c) >> 2;/*	printk("trap=%d\n",trap); */	if (trap == 11) {		if (((regs->cp0_cause >> CAUSEB_CE) & 3) == 1) {			regs->cp0_status |= ST0_CU1;			return;		}	}	/*	 * If we're in breakpoint() increment the PC	 */	if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst)				regs->cp0_epc += 4;	/*	 * If we were single_stepping, restore the opcodes hoisted	 * for the breakpoint[s].	 */	if (step_bp[0].addr) {		*(unsigned *)step_bp[0].addr = step_bp[0].val;		step_bp[0].addr = 0;		    		if (step_bp[1].addr) {			*(unsigned *)step_bp[1].addr = step_bp[1].val;			step_bp[1].addr = 0;		}	}	/*	 * If we were interrupted asynchronously by gdb, then a	 * breakpoint was set at the EPC of the interrupt so	 * that we'd wind up here with an interesting stack frame.	 */	if (async_bp.addr) {		*(unsigned *)async_bp.addr = async_bp.val;		async_bp.addr = 0;	}	stack = (long *)regs->reg29;			/* stack ptr */	sigval = computeSignal(trap);	/*	 * reply to host that an exception has occurred	 */	ptr = output_buffer;	/*	 * Send trap type (converted to signal)	 */	*ptr++ = 'T';	*ptr++ = hexchars[sigval >> 4];	*ptr++ = hexchars[sigval & 0xf];	/*	 * Send Error PC	 */	*ptr++ = hexchars[REG_EPC >> 4];	*ptr++ = hexchars[REG_EPC & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&regs->cp0_epc, ptr, 4, 0);	*ptr++ = ';';	/*	 * Send frame pointer	 */	*ptr++ = hexchars[REG_FP >> 4];	*ptr++ = hexchars[REG_FP & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&regs->reg30, ptr, 4, 0);	*ptr++ = ';';	/*	 * Send stack pointer	 */	*ptr++ = hexchars[REG_SP >> 4];	*ptr++ = hexchars[REG_SP & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&regs->reg29, ptr, 4, 0);	*ptr++ = ';';	*ptr++ = 0;	putpacket(output_buffer);	/* send it off... */	/*	 * Wait for input from remote GDB	 */	while (1) {		output_buffer[0] = 0;		getpacket(input_buffer);		switch (input_buffer[0])		{		case '?':			output_buffer[0] = 'S';			output_buffer[1] = hexchars[sigval >> 4];			output_buffer[2] = hexchars[sigval & 0xf];			output_buffer[3] = 0;			break;		case 'd':			/* toggle debug flag */			break;		/*		 * Return the value of the CPU registers		 */		case 'g':			ptr = output_buffer;			ptr = mem2hex((char *)&regs->reg0, ptr, 32*4, 0); /* r0...r31 */			ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*4, 0); /* cp0 */			ptr = mem2hex((char *)&regs->fpr0, ptr, 32*4, 0); /* f0...31 */			ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*4, 0); /* cp1 */			ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*4, 0); /* frp */			ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*4, 0); /* cp0 */			break;	  		/*		 * set the value of the CPU registers - return OK		 * FIXME: Needs to be written		 */		case 'G':		{#if 0			unsigned long *newsp, psr;			ptr = &input_buffer[1];			hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */			/*			 * See if the stack pointer has moved. If so, then copy the			 * saved locals and ins to the new location.			 */			newsp = (unsigned long *)registers[SP];			if (sp != newsp)				sp = memcpy(newsp, sp, 16 * 4);#endif			strcpy(output_buffer,"OK");		 }		break;		/*		 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA		 */		case 'm':			ptr = &input_buffer[1];			if (hexToInt(&ptr, &addr)				&& *ptr++ == ','				&& hexToInt(&ptr, &length)) {				if (mem2hex((char *)addr, output_buffer, length, 1))					break;				strcpy (output_buffer, "E03");			} else				strcpy(output_buffer,"E01");			break;		/*		 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK		 */		case 'M': 			ptr = &input_buffer[1];			if (hexToInt(&ptr, &addr)				&& *ptr++ == ','				&& hexToInt(&ptr, &length)				&& *ptr++ == ':') {				if (hex2mem(ptr, (char *)addr, length, 1))					strcpy(output_buffer, "OK");				else					strcpy(output_buffer, "E03");			}			else				strcpy(output_buffer, "E02");			break;		/*		 * cAA..AA    Continue at address AA..AA(optional)		 */		case 'c':    			/* try to read optional parameter, pc unchanged if no parm */			ptr = &input_buffer[1];			if (hexToInt(&ptr, &addr))				regs->cp0_epc = addr;	  			/*			 * Need to flush the instruction cache here, as we may			 * have deposited a breakpoint, and the icache probably			 * has no way of knowing that a data ref to some location			 * may have changed something that is in the instruction			 * cache.			 * NB: We flush both caches, just to be sure...			 */			flush_cache_all();			return;			/* NOTREACHED */			break;		/*		 * kill the program		 */		case 'k' :			break;		/* do nothing */		/*		 * Reset the whole machine (FIXME: system dependent)		 */		case 'r':			break;		/*		 * Step to next instruction		 */		case 's':			/*			 * There is no single step insn in the MIPS ISA, so we			 * use breakpoints and continue, instead.			 */			single_step(regs);			flush_cache_all();			return;			/* NOTREACHED */		/*		 * Set baud rate (bBB)		 * FIXME: Needs to be written		 */		case 'b':		{#if 0							int baudrate;			extern void set_timer_3();			ptr = &input_buffer[1];			if (!hexToInt(&ptr, &baudrate))			{				strcpy(output_buffer,"B01");				break;			}			/* Convert baud rate to uart clock divider */			switch (baudrate)			{				case 38400:					baudrate = 16;					break;				case 19200:					baudrate = 33;					break;				case 9600:					baudrate = 65;					break;				default:					baudrate = 0;					strcpy(output_buffer,"B02");					goto x1;			}			if (baudrate) {				putpacket("OK");	/* Ack before changing speed */				set_timer_3(baudrate); /* Set it */			}#endif		}		break;		}			/* switch */		/*		 * reply to the request		 */		putpacket(output_buffer);	} /* while */}/* * This function will generate a breakpoint exception.  It is used at the * beginning of a program to sync up with a debugger and can be used * otherwise as a quick means to stop program execution and "break" into * the debugger. */void breakpoint(void){	if (!initialized)		return;	__asm__ __volatile__("			.globl	breakinst			.set	noreorder			nopbreakinst:		break			nop			.set	reorder	");}void adel(void){	__asm__ __volatile__("			.globl	adel			la	$8,0x80000001			lw	$9,0($8)	");}#ifdef CONFIG_GDB_CONSOLEvoid gdb_puts(const char *str){	int l = strlen(str);	char outbuf[18];	outbuf[0]='O';	while(l) {		int i = (l>8)?8:l;		mem2hex((char *)str, &outbuf[1], i, 0);		outbuf[(i*2)+1]=0;		putpacket(outbuf); 		str += i;		l -= i;	}}static kdev_t gdb_console_dev(struct console *con){	return MKDEV(1, 3); /* /dev/null */}static void gdb_console_write(struct console *con, const char *s, unsigned n){	gdb_puts(s);}static struct console gdb_console = {	name:	"gdb",	write:	gdb_console_write,	device:	gdb_console_dev,	flags:	CON_PRINTBUFFER,	index:	-1};__init void register_gdb_console(void){	register_console(&gdb_console);}     #endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -