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

📄 gdb-stub.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	/*	 * 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;/* * Swap the interrupted EPC with our asynchronous breakpoint routine. * This is safer than stuffing the breakpoint in-place, since no cache * flushes (or resulting smp_call_functions) are required.  The * assumption is that only one CPU will be handling asynchronous bp's, * and only one can be active at a time. */extern spinlock_t smp_call_lock;void set_async_breakpoint(unsigned long *epc){	/* skip breaking into userland */	if ((*epc & 0x80000000) == 0)		return;#ifdef CONFIG_SMP	/* avoid deadlock if someone is make IPC */	if (spin_is_locked(&smp_call_lock))		return;#endif	async_bp.addr = *epc;	*epc = (unsigned long)async_breakpoint;}static void kgdb_wait(void *arg){	unsigned flags;	int cpu = smp_processor_id();	local_irq_save(flags);	__raw_spin_lock(&kgdb_cpulock[cpu]);	__raw_spin_unlock(&kgdb_cpulock[cpu]);	local_irq_restore(flags);}/* * GDB stub needs to call kgdb_wait on all processor with interrupts * disabled, so it uses it's own special variant. */static int kgdb_smp_call_kgdb_wait(void){#ifdef CONFIG_SMP	struct call_data_struct data;	int i, cpus = num_online_cpus() - 1;	int cpu = smp_processor_id();	/*	 * Can die spectacularly if this CPU isn't yet marked online	 */	BUG_ON(!cpu_online(cpu));	if (!cpus)		return 0;	if (spin_is_locked(&smp_call_lock)) {		/*		 * Some other processor is trying to make us do something		 * but we're not going to respond... give up		 */		return -1;		}	/*	 * We will continue here, accepting the fact that	 * the kernel may deadlock if another CPU attempts	 * to call smp_call_function now...	 */	data.func = kgdb_wait;	data.info = NULL;	atomic_set(&data.started, 0);	data.wait = 0;	spin_lock(&smp_call_lock);	call_data = &data;	mb();	/* Send a message to all other CPUs and wait for them to respond */	for (i = 0; i < NR_CPUS; i++)		if (cpu_online(i) && i != cpu)			core_send_ipi(i, SMP_CALL_FUNCTION);	/* Wait for response */	/* FIXME: lock-up detection, backtrace on lock-up */	while (atomic_read(&data.started) != cpus)		barrier();	call_data = NULL;	spin_unlock(&smp_call_lock);#endif	return 0;}/* * 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;	long addr;	int length;	char *ptr;	unsigned long *stack;	int i;	int bflag = 0;	kgdb_started = 1;	/*	 * acquire the big kgdb spinlock	 */	if (!spin_trylock(&kgdb_lock)) {		/*		 * some other CPU has the lock, we should go back to		 * receive the gdb_wait IPC		 */		return;	}	/*	 * If we're in async_breakpoint(), restore the real EPC from	 * the breakpoint.	 */	if (regs->cp0_epc == (unsigned long)async_breakinst) {		regs->cp0_epc = async_bp.addr;		async_bp.addr = 0;	}	/*	 * acquire the CPU spinlocks	 */	for (i = num_online_cpus()-1; i >= 0; i--)		if (__raw_spin_trylock(&kgdb_cpulock[i]) == 0)			panic("kgdb: couldn't get cpulock %d\n", i);	/*	 * force other cpus to enter kgdb	 */	kgdb_smp_call_kgdb_wait();	/*	 * If we're in breakpoint() increment the PC	 */	trap = (regs->cp0_cause & 0x7c) >> 2;	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;		}	}	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, sizeof(long), 0);	*ptr++ = ';';	/*	 * Send frame pointer	 */	*ptr++ = hexchars[REG_FP >> 4];	*ptr++ = hexchars[REG_FP & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&regs->reg30, ptr, sizeof(long), 0);	*ptr++ = ';';	/*	 * Send stack pointer	 */	*ptr++ = hexchars[REG_SP >> 4];	*ptr++ = hexchars[REG_SP & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&regs->reg29, ptr, sizeof(long), 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;		/*		 * Detach debugger; let CPU run		 */		case 'D':			putpacket(output_buffer);			goto finish_kgdb;			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*sizeof(long), 0); /* r0...r31 */			ptr = mem2hex((char *)&regs->cp0_status, ptr, 6*sizeof(long), 0); /* cp0 */			ptr = mem2hex((char *)&regs->fpr0, ptr, 32*sizeof(long), 0); /* f0...31 */			ptr = mem2hex((char *)&regs->cp1_fsr, ptr, 2*sizeof(long), 0); /* cp1 */			ptr = mem2hex((char *)&regs->frame_ptr, ptr, 2*sizeof(long), 0); /* frp */			ptr = mem2hex((char *)&regs->cp0_index, ptr, 16*sizeof(long), 0); /* cp0 */			break;		/*		 * set the value of the CPU registers - return OK		 */		case 'G':		{			ptr = &input_buffer[1];			hex2mem(ptr, (char *)&regs->reg0, 32*sizeof(long), 0, 0);			ptr += 32*(2*sizeof(long));			hex2mem(ptr, (char *)&regs->cp0_status, 6*sizeof(long), 0, 0);			ptr += 6*(2*sizeof(long));			hex2mem(ptr, (char *)&regs->fpr0, 32*sizeof(long), 0, 0);			ptr += 32*(2*sizeof(long));			hex2mem(ptr, (char *)&regs->cp1_fsr, 2*sizeof(long), 0, 0);			ptr += 2*(2*sizeof(long));			hex2mem(ptr, (char *)&regs->frame_ptr, 2*sizeof(long), 0, 0);			ptr += 2*(2*sizeof(long));			hex2mem(ptr, (char *)&regs->cp0_index, 16*sizeof(long), 0, 0);			strcpy(output_buffer,"OK");		 }		break;		/*		 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA		 */		case 'm':			ptr = &input_buffer[1];			if (hexToLong(&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;		/*		 * XAA..AA,LLLL: Write LLLL escaped binary bytes at address AA.AA		 */		case 'X':			bflag = 1;			/* fall through */		/*		 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK		 */		case 'M':			ptr = &input_buffer[1];			if (hexToLong(&ptr, &addr)				&& *ptr++ == ','				&& hexToInt(&ptr, &length)				&& *ptr++ == ':') {				if (hex2mem(ptr, (char *)addr, length, bflag, 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 (hexToLong(&ptr, &addr))				regs->cp0_epc = addr;			goto exit_kgdb_exception;			break;		/*		 * kill the program; let us try to restart the machine		 * Reset the whole machine.		 */		case 'k':		case 'r':			machine_restart("kgdb restarts machine");			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);			goto exit_kgdb_exception;			/* NOTREACHED */			break;		/*		 * 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 */	return;finish_kgdb:	restore_debug_traps();exit_kgdb_exception:	/* release locks so other CPUs can go */	for (i = num_online_cpus()-1; i >= 0; i--)		__raw_spin_unlock(&kgdb_cpulock[i]);	spin_unlock(&kgdb_lock);	__flush_cache_all();	return;}/* * 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\n\t"			".set\tnoreorder\n\t"			"nop\n"			"breakinst:\tbreak\n\t"			"nop\n\t"			".set\treorder"			);}/* Nothing but the break; don't pollute any registers */void async_breakpoint(void){	__asm__ __volatile__(			".globl	async_breakinst\n\t"			".set\tnoreorder\n\t"			"nop\n"			"async_breakinst:\tbreak\n\t"			"nop\n\t"			".set\treorder"			);}void adel(void){	__asm__ __volatile__(			".globl\tadel\n\t"			"lui\t$8,0x8000\n\t"			"lw\t$9,1($8)\n\t"			);}/* * malloc is needed by gdb client in "call func()", even a private one * will make gdb happy */static void * __attribute_used__ malloc(size_t size){	return kmalloc(size, GFP_ATOMIC);}static void __attribute_used__ free (void *where){	kfree(where);}#ifdef CONFIG_GDB_CONSOLEvoid gdb_putsn(const char *str, int l){	char outbuf[18];	if (!kgdb_started)		return;	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 void gdb_console_write(struct console *con, const char *s, unsigned n){	gdb_putsn(s, n);}static struct console gdb_console = {	.name	= "gdb",	.write	= gdb_console_write,	.flags	= CON_PRINTBUFFER,	.index	= -1};static int __init register_gdb_console(void){	register_console(&gdb_console);	return 0;}console_initcall(register_gdb_console);#endif

⌨️ 快捷键说明

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