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

📄 kgdb.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Read watchpoints are set as access watchpoints, because of GDB's	   inability to deal with pure read watchpoints. */	if (type == '3')		type = '4';	if (type == '1') {		/* Hardware breakpoint. */		/* Bit 0 in BP_CTRL holds the configuration for I0. */		if (!(sreg.s0_3 & 0x1)) {			/* Not in use. */			gdb_cris_strcpy(output_buffer, error_message[E04]);			return;		}		/* Deconfigure. */		sreg.s1_3 = 0;		sreg.s2_3 = 0;		sreg.s0_3 &= ~1;	} else {		int bp;		unsigned int *bp_d_regs = &sreg.s3_3;		/* Try to find a watchpoint that is configured for the		   specified range, then check that read/write also matches. */		/* Ugly pointer arithmetic, since I cannot rely on a		   single switch (addr) as there may be several watchpoints with		   the same start address for example. */		for (bp = 0; bp < 6; bp++) {			if (bp_d_regs[bp * 2] == addr &&			    bp_d_regs[bp * 2 + 1] == (addr + len - 1)) {				/* Matching range. */				int bitpos = 2 + bp * 4;				int rw_bits;				/* Read/write bits for this BP. */				rw_bits = (sreg.s0_3 & (0x3 << bitpos)) >> bitpos;				if ((type == '3' && rw_bits == 0x1) ||				    (type == '2' && rw_bits == 0x2) ||				    (type == '4' && rw_bits == 0x3)) {					/* Read/write matched. */					break;				}			}		}		if (bp > 5) {			/* No watchpoint matched. */			gdb_cris_strcpy(output_buffer, error_message[E04]);			return;		}		/* Found a matching watchpoint. Now, deconfigure it by		   both disabling read/write in bp_ctrl and zeroing its		   start/end addresses. */		sreg.s0_3 &= ~(3 << (2 + (bp * 4)));		bp_d_regs[bp * 2] = 0;		bp_d_regs[bp * 2 + 1] = 0;	}	/* Note that we don't clear the S1 flag here. It's done when continuing.  */	gdb_cris_strcpy(output_buffer, "OK");}/* All expected commands are sent from remote.c. Send a response according   to the description in remote.c. */voidhandle_exception(int sigval){	/* Avoid warning of not used. */	USEDFUN(handle_exception);	USEDVAR(internal_stack[0]);	register_fixup(sigval);	/* Send response. */	stub_is_stopped(sigval);	for (;;) {		output_buffer[0] = '\0';		getpacket(input_buffer);		switch (input_buffer[0]) {			case 'g':				/* Read registers: g				   Success: Each byte of register data is described by two hex digits.				   Registers are in the internal order for GDB, and the bytes				   in a register  are in the same order the machine uses.				   Failure: void. */			{				char *buf;				/* General and special registers. */				buf = mem2hex(output_buffer, (char *)&reg, sizeof(registers));				/* Support registers. */				/* -1 because of the null termination that mem2hex adds. */				mem2hex(buf,					(char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)),					16 * sizeof(unsigned int));				break;			}			case 'G':				/* Write registers. GXX..XX				   Each byte of register data  is described by two hex digits.				   Success: OK				   Failure: void. */				/* General and special registers. */				hex2mem((char *)&reg, &input_buffer[1], sizeof(registers));				/* Support registers. */				hex2mem((char *)&sreg + (reg.srs * 16 * sizeof(unsigned int)),					&input_buffer[1] + sizeof(registers),					16 * sizeof(unsigned int));				gdb_cris_strcpy(output_buffer, "OK");				break;			case 'P':				/* Write register. Pn...=r...				   Write register n..., hex value without 0x, with value r...,				   which contains a hex value without 0x and two hex digits				   for each byte in the register (target byte order). P1f=11223344 means				   set register 31 to 44332211.				   Success: OK				   Failure: E02, E05 */				{					char *suffix;					int regno = gdb_cris_strtol(&input_buffer[1], &suffix, 16);					int status;					status = write_register(regno, suffix+1);					switch (status) {						case E02:							/* Do not support read-only registers. */							gdb_cris_strcpy(output_buffer, error_message[E02]);							break;						case E05:							/* Do not support non-existing registers. */							gdb_cris_strcpy(output_buffer, error_message[E05]);							break;						default:							/* Valid register number. */							gdb_cris_strcpy(output_buffer, "OK");							break;					}				}				break;			case 'm':				/* Read from memory. mAA..AA,LLLL				   AA..AA is the address and LLLL is the length.				   Success: XX..XX is the memory content.  Can be fewer bytes than				   requested if only part of the data may be read. m6000120a,6c means				   retrieve 108 byte from base address 6000120a.				   Failure: void. */				{                                        char *suffix;					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&input_buffer[1],                                                                                               &suffix, 16);					int len = gdb_cris_strtol(suffix+1, 0, 16);					/* Bogus read (i.e. outside the kernel's					   segment)? . */					if (!((unsigned int)addr >= 0xc0000000 &&					      (unsigned int)addr < 0xd0000000))						addr = NULL;                                        mem2hex(output_buffer, addr, len);                                }				break;			case 'X':				/* Write to memory. XAA..AA,LLLL:XX..XX				   AA..AA is the start address,  LLLL is the number of bytes, and				   XX..XX is the binary data.				   Success: OK				   Failure: void. */			case 'M':				/* Write to memory. MAA..AA,LLLL:XX..XX				   AA..AA is the start address,  LLLL is the number of bytes, and				   XX..XX is the hexadecimal data.				   Success: OK				   Failure: void. */				{					char *lenptr;					char *dataptr;					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&input_buffer[1],										      &lenptr, 16);					int len = gdb_cris_strtol(lenptr+1, &dataptr, 16);					if (*lenptr == ',' && *dataptr == ':') {						if (input_buffer[0] == 'M') {							hex2mem(addr, dataptr + 1, len);						} else /* X */ {							bin2mem(addr, dataptr + 1, len);						}						gdb_cris_strcpy(output_buffer, "OK");					}					else {						gdb_cris_strcpy(output_buffer, error_message[E06]);					}				}				break;			case 'c':				/* Continue execution. cAA..AA				   AA..AA is the address where execution is resumed. If AA..AA is				   omitted, resume at the present address.				   Success: return to the executing thread.				   Failure: will never know. */				if (input_buffer[1] != '\0') {					/* FIXME: Doesn't handle address argument. */					gdb_cris_strcpy(output_buffer, error_message[E04]);					break;				}				/* Before continuing, make sure everything is set up correctly. */				/* Set the SPC to some unlikely value.  */				reg.spc = 0;				/* Set the S1 flag to 0 unless some watchpoint is enabled (since setting				   S1 to 0 would also disable watchpoints). (Note that bits 26-31 in BP_CTRL				   are reserved, so don't check against those). */				if ((sreg.s0_3 & 0x3fff) == 0) {					reg.ccs &= ~(1 << (S_CCS_BITNR + CCS_SHIFT));				}				return;			case 's':				/* Step. sAA..AA				   AA..AA is the address where execution is resumed. If AA..AA is				   omitted, resume at the present address. Success: return to the				   executing thread. Failure: will never know. */				if (input_buffer[1] != '\0') {					/* FIXME: Doesn't handle address argument. */					gdb_cris_strcpy(output_buffer, error_message[E04]);					break;				}				/* Set the SPC to PC, which is where we'll return				   (deduced previously). */				reg.spc = reg.pc;				/* Set the S1 (first stacked, not current) flag, which will				   kick into action when we rfe. */				reg.ccs |= (1 << (S_CCS_BITNR + CCS_SHIFT));				return;                       case 'Z':                               /* Insert breakpoint or watchpoint, Ztype,addr,length.                                  Remote protocol says: A remote target shall return an empty string                                  for an unrecognized breakpoint or watchpoint packet type. */                               {                                       char *lenptr;                                       char *dataptr;                                       int addr = gdb_cris_strtol(&input_buffer[3], &lenptr, 16);                                       int len = gdb_cris_strtol(lenptr + 1, &dataptr, 16);                                       char type = input_buffer[1];				       insert_watchpoint(type, addr, len);                                       break;                               }                       case 'z':                               /* Remove breakpoint or watchpoint, Ztype,addr,length.                                  Remote protocol says: A remote target shall return an empty string                                  for an unrecognized breakpoint or watchpoint packet type. */                               {                                       char *lenptr;                                       char *dataptr;                                       int addr = gdb_cris_strtol(&input_buffer[3], &lenptr, 16);                                       int len = gdb_cris_strtol(lenptr + 1, &dataptr, 16);                                       char type = input_buffer[1];                                       remove_watchpoint(type, addr, len);                                       break;                               }			case '?':				/* The last signal which caused a stop. ?				   Success: SAA, where AA is the signal number.				   Failure: void. */				output_buffer[0] = 'S';				output_buffer[1] = highhex(sigval);				output_buffer[2] = lowhex(sigval);				output_buffer[3] = 0;				break;			case 'D':				/* Detach from host. D				   Success: OK, and return to the executing thread.				   Failure: will never know */				putpacket("OK");				return;			case 'k':			case 'r':				/* kill request or reset request.				   Success: restart of target.				   Failure: will never know. */				kill_restart();				break;			case 'C':			case 'S':			case '!':			case 'R':			case 'd':				/* Continue with signal sig. Csig;AA..AA				   Step with signal sig. Ssig;AA..AA				   Use the extended remote protocol. !				   Restart the target system. R0				   Toggle debug flag. d				   Search backwards. tAA:PP,MM				   Not supported: E04 */				/* FIXME: What's the difference between not supported				   and ignored (below)? */				gdb_cris_strcpy(output_buffer, error_message[E04]);				break;			default:				/* The stub should ignore other request and send an empty				   response ($#<checksum>). This way we can extend the protocol and GDB				   can tell whether the stub it is talking to uses the old or the new. */				output_buffer[0] = 0;				break;		}		putpacket(output_buffer);	}}voidkgdb_init(void){	reg_intr_vect_rw_mask intr_mask;	reg_ser_rw_intr_mask ser_intr_mask;	/* Configure the kgdb serial port. */#if defined(CONFIG_ETRAX_KGDB_PORT0)	/* Note: no shortcut registered (not handled by multiple_interrupt).	   See entry.S.  */	set_exception_vector(SER0_INTR_VECT, kgdb_handle_exception);	/* Enable the ser irq in the global config. */	intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);	intr_mask.ser0 = 1;	REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);	ser_intr_mask = REG_RD(ser, regi_ser0, rw_intr_mask);	ser_intr_mask.data_avail = regk_ser_yes;	REG_WR(ser, regi_ser0, rw_intr_mask, ser_intr_mask);#elif defined(CONFIG_ETRAX_KGDB_PORT1)	/* Note: no shortcut registered (not handled by multiple_interrupt).	   See entry.S.  */	set_exception_vector(SER1_INTR_VECT, kgdb_handle_exception);	/* Enable the ser irq in the global config. */	intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);	intr_mask.ser1 = 1;	REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);	ser_intr_mask = REG_RD(ser, regi_ser1, rw_intr_mask);	ser_intr_mask.data_avail = regk_ser_yes;	REG_WR(ser, regi_ser1, rw_intr_mask, ser_intr_mask);#elif defined(CONFIG_ETRAX_KGDB_PORT2)	/* Note: no shortcut registered (not handled by multiple_interrupt).	   See entry.S.  */	set_exception_vector(SER2_INTR_VECT, kgdb_handle_exception);	/* Enable the ser irq in the global config. */	intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);	intr_mask.ser2 = 1;	REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);	ser_intr_mask = REG_RD(ser, regi_ser2, rw_intr_mask);	ser_intr_mask.data_avail = regk_ser_yes;	REG_WR(ser, regi_ser2, rw_intr_mask, ser_intr_mask);#elif defined(CONFIG_ETRAX_KGDB_PORT3)	/* Note: no shortcut registered (not handled by multiple_interrupt).	   See entry.S.  */	set_exception_vector(SER3_INTR_VECT, kgdb_handle_exception);	/* Enable the ser irq in the global config. */	intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);	intr_mask.ser3 = 1;	REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);	ser_intr_mask = REG_RD(ser, regi_ser3, rw_intr_mask);	ser_intr_mask.data_avail = regk_ser_yes;	REG_WR(ser, regi_ser3, rw_intr_mask, ser_intr_mask);#endif}/* Performs a complete re-start from scratch. */static voidkill_restart(void){	machine_restart("");}/* Use this static breakpoint in the start-up only. */voidbreakpoint(void){	kgdb_started = 1;	dynamic_bp = 0;     /* This is a static, not a dynamic breakpoint. */	__asm__ volatile ("break 8"); /* Jump to kgdb_handle_breakpoint. */}/****************************** End of file **********************************/

⌨️ 快捷键说明

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