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

📄 kgdb_stub.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	char *src;	int runlen;	int encode;	do {		src = buffer;		put_debug_char('$');		checksum = 0;		/* Continue while we still have chars left */		while (*src) {			/* Check for runs up to 99 chars long */			for (runlen = 1; runlen < 99; runlen++) {				if (src[0] != src[runlen])					break;			}			if (runlen > 3) {				/* Got a useful amount, send encoding */				encode = runlen + ' ' - 4;				put_debug_char(*src);   checksum += *src;				put_debug_char('*');    checksum += '*';				put_debug_char(encode); checksum += encode;				src += runlen;			} else {				/* Otherwise just send the current char */				put_debug_char(*src);   checksum += *src;				src += 1;			}		}		/* '#' Separator, put high and low components of checksum */		put_debug_char('#');		put_debug_char(highhex(checksum));		put_debug_char(lowhex(checksum));	}	while ((get_debug_char()) != '+');	/* While no ack */}/* A bus error has occurred - perform a longjmp to return execution and   allow handling of the error */static void kgdb_handle_bus_error(void){	longjmp(rem_com_env, 1);}/* Translate SH-3/4 exception numbers to unix-like signal values */static int compute_signal(const int excep_code){	int sigval;	switch (excep_code) {	case INVALID_INSN_VEC:	case INVALID_SLOT_VEC:		sigval = SIGILL;		break;	case ADDRESS_ERROR_LOAD_VEC:	case ADDRESS_ERROR_STORE_VEC:		sigval = SIGSEGV;		break;	case SERIAL_BREAK_VEC:	case NMI_VEC:		sigval = SIGINT;		break;	case USER_BREAK_VEC:	case TRAP_VEC:		sigval = SIGTRAP;		break;	default:		sigval = SIGBUS;	/* "software generated" */		break;	}	return (sigval);}/* Make a local copy of the registers passed into the handler (bletch) */static void kgdb_regs_to_gdb_regs(const struct kgdb_regs *regs,				  int *gdb_regs){	gdb_regs[R0] = regs->regs[R0];	gdb_regs[R1] = regs->regs[R1];	gdb_regs[R2] = regs->regs[R2];	gdb_regs[R3] = regs->regs[R3];	gdb_regs[R4] = regs->regs[R4];	gdb_regs[R5] = regs->regs[R5];	gdb_regs[R6] = regs->regs[R6];	gdb_regs[R7] = regs->regs[R7];	gdb_regs[R8] = regs->regs[R8];	gdb_regs[R9] = regs->regs[R9];	gdb_regs[R10] = regs->regs[R10];	gdb_regs[R11] = regs->regs[R11];	gdb_regs[R12] = regs->regs[R12];	gdb_regs[R13] = regs->regs[R13];	gdb_regs[R14] = regs->regs[R14];	gdb_regs[R15] = regs->regs[R15];	gdb_regs[PC] = regs->pc;	gdb_regs[PR] = regs->pr;	gdb_regs[GBR] = regs->gbr;	gdb_regs[MACH] = regs->mach;	gdb_regs[MACL] = regs->macl;	gdb_regs[SR] = regs->sr;	gdb_regs[VBR] = regs->vbr;}/* Copy local gdb registers back to kgdb regs, for later copy to kernel */static void gdb_regs_to_kgdb_regs(const int *gdb_regs,				  struct kgdb_regs *regs){	regs->regs[R0] = gdb_regs[R0];	regs->regs[R1] = gdb_regs[R1];	regs->regs[R2] = gdb_regs[R2];	regs->regs[R3] = gdb_regs[R3];	regs->regs[R4] = gdb_regs[R4];	regs->regs[R5] = gdb_regs[R5];	regs->regs[R6] = gdb_regs[R6];	regs->regs[R7] = gdb_regs[R7];	regs->regs[R8] = gdb_regs[R8];	regs->regs[R9] = gdb_regs[R9];	regs->regs[R10] = gdb_regs[R10];	regs->regs[R11] = gdb_regs[R11];	regs->regs[R12] = gdb_regs[R12];	regs->regs[R13] = gdb_regs[R13];	regs->regs[R14] = gdb_regs[R14];	regs->regs[R15] = gdb_regs[R15];	regs->pc = gdb_regs[PC];	regs->pr = gdb_regs[PR];	regs->gbr = gdb_regs[GBR];	regs->mach = gdb_regs[MACH];	regs->macl = gdb_regs[MACL];	regs->sr = gdb_regs[SR];	regs->vbr = gdb_regs[VBR];}#ifdef CONFIG_KGDB_THREAD/* Make a local copy of registers from the specified thread */asmlinkage void ret_from_fork(void);static void thread_regs_to_gdb_regs(const struct task_struct *thread,				    int *gdb_regs){	int regno;	int *tregs;	/* Initialize to zero */	for (regno = 0; regno < MAXREG; regno++)		gdb_regs[regno] = 0;	/* Just making sure... */	if (thread == NULL)		return;	/* A new fork has pt_regs on the stack from a fork() call */	if (thread->thread.pc == (unsigned long)ret_from_fork) {		int vbr_val;		struct pt_regs *kregs;		kregs = (struct pt_regs*)thread->thread.sp;		gdb_regs[R0] = kregs->regs[R0];		gdb_regs[R1] = kregs->regs[R1];		gdb_regs[R2] = kregs->regs[R2];		gdb_regs[R3] = kregs->regs[R3];		gdb_regs[R4] = kregs->regs[R4];		gdb_regs[R5] = kregs->regs[R5];		gdb_regs[R6] = kregs->regs[R6];		gdb_regs[R7] = kregs->regs[R7];		gdb_regs[R8] = kregs->regs[R8];		gdb_regs[R9] = kregs->regs[R9];		gdb_regs[R10] = kregs->regs[R10];		gdb_regs[R11] = kregs->regs[R11];		gdb_regs[R12] = kregs->regs[R12];		gdb_regs[R13] = kregs->regs[R13];		gdb_regs[R14] = kregs->regs[R14];		gdb_regs[R15] = kregs->regs[R15];		gdb_regs[PC] = kregs->pc;		gdb_regs[PR] = kregs->pr;		gdb_regs[GBR] = kregs->gbr;		gdb_regs[MACH] = kregs->mach;		gdb_regs[MACL] = kregs->macl;		gdb_regs[SR] = kregs->sr;		asm("stc vbr, %0":"=r"(vbr_val));		gdb_regs[VBR] = vbr_val;		return;	}	/* Otherwise, we have only some registers from switch_to() */	tregs = (int *)thread->thread.sp;	gdb_regs[R15] = (int)tregs;	gdb_regs[R14] = *tregs++;	gdb_regs[R13] = *tregs++;	gdb_regs[R12] = *tregs++;	gdb_regs[R11] = *tregs++;	gdb_regs[R10] = *tregs++;	gdb_regs[R9] = *tregs++;	gdb_regs[R8] = *tregs++;	gdb_regs[PR] = *tregs++;	gdb_regs[GBR] = *tregs++;	gdb_regs[PC] = thread->thread.pc;}#endif /* CONFIG_KGDB_THREAD *//* Calculate the new address for after a step */static short *get_step_address(void){	short op = *(short *) trap_registers.pc;	long addr;	/* BT */	if (OPCODE_BT(op)) {		if (trap_registers.sr & SR_T_BIT_MASK)			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);		else			addr = trap_registers.pc + 2;	}	/* BTS */	else if (OPCODE_BTS(op)) {		if (trap_registers.sr & SR_T_BIT_MASK)			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);		else			addr = trap_registers.pc + 4;	/* Not in delay slot */	}	/* BF */	else if (OPCODE_BF(op)) {		if (!(trap_registers.sr & SR_T_BIT_MASK))			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);		else			addr = trap_registers.pc + 2;	}	/* BFS */	else if (OPCODE_BFS(op)) {		if (!(trap_registers.sr & SR_T_BIT_MASK))			addr = trap_registers.pc + 4 + OPCODE_BTF_DISP(op);		else			addr = trap_registers.pc + 4;	/* Not in delay slot */	}	/* BRA */	else if (OPCODE_BRA(op))		addr = trap_registers.pc + 4 + OPCODE_BRA_DISP(op);	/* BRAF */	else if (OPCODE_BRAF(op))		addr = trap_registers.pc + 4		    + trap_registers.regs[OPCODE_BRAF_REG(op)];	/* BSR */	else if (OPCODE_BSR(op))		addr = trap_registers.pc + 4 + OPCODE_BSR_DISP(op);	/* BSRF */	else if (OPCODE_BSRF(op))		addr = trap_registers.pc + 4		    + trap_registers.regs[OPCODE_BSRF_REG(op)];	/* JMP */	else if (OPCODE_JMP(op))		addr = trap_registers.regs[OPCODE_JMP_REG(op)];	/* JSR */	else if (OPCODE_JSR(op))		addr = trap_registers.regs[OPCODE_JSR_REG(op)];	/* RTS */	else if (OPCODE_RTS(op))		addr = trap_registers.pr;	/* RTE */	else if (OPCODE_RTE(op))		addr = trap_registers.regs[15];	/* Other */	else		addr = trap_registers.pc + 2;	kgdb_flush_icache_range(addr, addr + 2);	return (short *) addr;}/* Set up a single-step.  Replace the instruction immediately after the    current instruction (i.e. next in the expected flow of control) with a   trap instruction, so that returning will cause only a single instruction   to be executed. Note that this model is slightly broken for instructions   with delay slots (e.g. B[TF]S, BSR, BRA etc), where both the branch   and the instruction in the delay slot will be executed. */static void do_single_step(void){	unsigned short *addr = 0;	/* Determine where the target instruction will send us to */	addr = get_step_address();	stepped_address = (int)addr;	/* Replace it */	stepped_opcode = *(short *)addr;	*addr = STEP_OPCODE;	/* Flush and return */	kgdb_flush_icache_range((long) addr, (long) addr + 2);	return;}/* Undo a single step */static void undo_single_step(void){	/* If we have stepped, put back the old instruction */	/* Use stepped_address in case we stopped elsewhere */	if (stepped_opcode != 0) {		*(short*)stepped_address = stepped_opcode;		kgdb_flush_icache_range(stepped_address, stepped_address + 2);	}	stepped_opcode = 0;}/* Send a signal message */static void send_signal_msg(const int signum){#ifndef CONFIG_KGDB_THREAD	out_buffer[0] = 'S';	out_buffer[1] = highhex(signum);	out_buffer[2] = lowhex(signum);	out_buffer[3] = 0;	put_packet(out_buffer);#else /* CONFIG_KGDB_THREAD */	int threadid;	threadref thref;	char *out = out_buffer;	const char *tstring = "thread";	*out++ = 'T';	*out++ = highhex(signum);	*out++ = lowhex(signum);	while (*tstring) {		*out++ = *tstring++;	}	*out++ = ':';	threadid = trapped_thread->pid;	if (threadid == 0) threadid = PID_MAX;	int_to_threadref(&thref, threadid);	pack_threadid(out, &thref);	out += BUF_THREAD_ID_SIZE;	*out++ = ';';	*out = 0;	put_packet(out_buffer);#endif /* CONFIG_KGDB_THREAD */}/* Reply that all was well */static void send_ok_msg(void){	strcpy(out_buffer, "OK");	put_packet(out_buffer);}/* Reply that an error occurred */static void send_err_msg(void){	strcpy(out_buffer, "E01");	put_packet(out_buffer);}/* Empty message indicates unrecognised command */static void send_empty_msg(void){	put_packet("");}/* Read memory due to 'm' message */static void read_mem_msg(void){	char *ptr;	int addr;	int length;	/* Jmp, disable bus error handler */	if (setjmp(rem_com_env) == 0) {		kgdb_nofault = 1;		/* Walk through, have m<addr>,<length> */		ptr = &in_buffer[1];		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))			if (hex_to_int(&ptr, &length)) {				ptr = 0;				if (length * 2 > OUTBUFMAX)					length = OUTBUFMAX / 2;				mem_to_hex((char *) addr, out_buffer, length);			}		if (ptr)			send_err_msg();		else			put_packet(out_buffer);	} else		send_err_msg();	/* Restore bus error handler */	kgdb_nofault = 0;}/* Write memory due to 'M' or 'X' message */static void write_mem_msg(int binary){	char *ptr;	int addr;	int length;	if (setjmp(rem_com_env) == 0) {		kgdb_nofault = 1;		/* Walk through, have M<addr>,<length>:<data> */		ptr = &in_buffer[1];		if (hex_to_int(&ptr, &addr) && (*ptr++ == ','))			if (hex_to_int(&ptr, &length) && (*ptr++ == ':')) {				if (binary)					ebin_to_mem(ptr, (char*)addr, length);				else					hex_to_mem(ptr, (char*)addr, length);				kgdb_flush_icache_range(addr, addr + length);				ptr = 0;				send_ok_msg();			}		if (ptr)			send_err_msg();	} else		send_err_msg();	/* Restore bus error handler */	kgdb_nofault = 0;}/* Continue message  */static void continue_msg(void){	/* Try to read optional parameter, PC unchanged if none */	char *ptr = &in_buffer[1];	int addr;	if (hex_to_int(&ptr, &addr))		trap_registers.pc = addr;}/* Continue message with signal */static void continue_with_sig_msg(void){	int signal;	char *ptr = &in_buffer[1];	int addr;	/* Report limitation */	kgdb_to_gdb("Cannot force signal in kgdb, continuing anyway.\n");	/* Signal */	hex_to_int(&ptr, &signal);	if (*ptr == ';')		ptr++;	/* Optional address */	if (hex_to_int(&ptr, &addr))		trap_registers.pc = addr;}/* Step message */static void step_msg(void){	continue_msg();	do_single_step();}/* Step message with signal */static void step_with_sig_msg(void){	continue_with_sig_msg();	do_single_step();}/* Send register contents */static void send_regs_msg(void){#ifdef CONFIG_KGDB_THREAD	if (!current_thread)		kgdb_regs_to_gdb_regs(&trap_registers, registers);	else		thread_regs_to_gdb_regs(current_thread, registers);#else	kgdb_regs_to_gdb_regs(&trap_registers, registers);#endif

⌨️ 快捷键说明

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