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

📄 sparc-stub.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* Assembler code is   *mem++ = ch;   with return 0 on fault */		__asm__(			"\n1:\n\t"			"stb %1, [%0]\n\t"			"inc %0\n\t"			".section .fixup,#alloc,#execinstr\n\t"			".align 4\n"			"2:\n\t"			"retl\n\t"			" mov 0, %%o0\n\t"			".section __ex_table, #alloc\n\t"			".align 4\n\t"			".word 1b, 2b\n\t"			".text\n"			: "=r" (mem) : "r" (ch) , "0" (mem));	}	return mem;}/* This table contains the mapping between SPARC hardware trap types, and   signals, which are primarily what GDB understands.  It also indicates   which hardware traps we need to commandeer when initializing the stub. */static struct hard_trap_info{  unsigned char tt;		/* Trap type code for SPARC */  unsigned char signo;		/* Signal that we map this trap into */} hard_trap_info[] = {  {SP_TRAP_SBPT, SIGTRAP},      /* ta 1 - Linux/KGDB software breakpoint */  {0, 0}			/* Must be last */};/* Set up exception handlers for tracing and breakpoints */voidset_debug_traps(void){	struct hard_trap_info *ht;	unsigned long flags;	save_and_cli(flags);#if 0	/* Have to sort this out. This cannot be done after initialization. */	BTFIXUPSET_CALL(flush_cache_all, flush_cache_all_nop, BTFIXUPCALL_NOP);#endif	/* Initialize our copy of the Linux Sparc trap table */	eh_init();	for (ht = hard_trap_info; ht->tt && ht->signo; ht++) {		/* Only if it doesn't destroy our fault handlers */		if((ht->tt != SP_TRAP_TFLT) && 		   (ht->tt != SP_TRAP_DFLT))			exceptionHandler(ht->tt, trap_low);	}	/* In case GDB is started before us, ack any packets (presumably	 * "$?#xx") sitting there.	 *	 * I've found this code causes more problems than it solves,	 * so that's why it's commented out.  GDB seems to work fine	 * now starting either before or after the kernel   -bwb	 */#if 0	while((c = getDebugChar()) != '$');	while((c = getDebugChar()) != '#');	c = getDebugChar(); /* eat first csum byte */	c = getDebugChar(); /* eat second csum byte */	putDebugChar('+'); /* ack it */#endif	initialized = 1; /* connect! */	restore_flags(flags);}/* Convert the SPARC hardware trap type code to a unix signal number. */static intcomputeSignal(int tt){	struct hard_trap_info *ht;	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)		if (ht->tt == tt)			return ht->signo;	return SIGHUP;         /* default for things we don't know about */}/* * While we find nice hex chars, build an int. * Return number of chars processed. */static inthexToInt(char **ptr, int *intValue){	int numChars = 0;	int hexValue;	*intValue = 0;	while (**ptr) {		hexValue = hex(**ptr);		if (hexValue < 0)			break;		*intValue = (*intValue << 4) | hexValue;		numChars ++;		(*ptr)++;	}	return (numChars);}/* * 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. */extern void breakinst(void);voidhandle_exception (unsigned long *registers){	int tt;       /* Trap type */	int sigval;	int addr;	int length;	char *ptr;	unsigned long *sp;	/* First, we must force all of the windows to be spilled out */	asm("save %sp, -64, %sp\n\t"	    "save %sp, -64, %sp\n\t"	    "save %sp, -64, %sp\n\t"	    "save %sp, -64, %sp\n\t"	    "save %sp, -64, %sp\n\t"	    "save %sp, -64, %sp\n\t"	    "save %sp, -64, %sp\n\t"	    "save %sp, -64, %sp\n\t"	    "restore\n\t"	    "restore\n\t"	    "restore\n\t"	    "restore\n\t"	    "restore\n\t"	    "restore\n\t"	    "restore\n\t"	    "restore\n\t");	lock_kernel();	if (registers[PC] == (unsigned long)breakinst) {		/* Skip over breakpoint trap insn */		registers[PC] = registers[NPC];		registers[NPC] += 4;	}	sp = (unsigned long *)registers[SP];	tt = (registers[TBR] >> 4) & 0xff;	/* reply to host that an exception has occurred */	sigval = computeSignal(tt);	ptr = remcomOutBuffer;	*ptr++ = 'T';	*ptr++ = hexchars[sigval >> 4];	*ptr++ = hexchars[sigval & 0xf];	*ptr++ = hexchars[PC >> 4];	*ptr++ = hexchars[PC & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&registers[PC], ptr, 4);	*ptr++ = ';';	*ptr++ = hexchars[FP >> 4];	*ptr++ = hexchars[FP & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *) (sp + 8 + 6), ptr, 4); /* FP */	*ptr++ = ';';	*ptr++ = hexchars[SP >> 4];	*ptr++ = hexchars[SP & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&sp, ptr, 4);	*ptr++ = ';';	*ptr++ = hexchars[NPC >> 4];	*ptr++ = hexchars[NPC & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&registers[NPC], ptr, 4);	*ptr++ = ';';	*ptr++ = hexchars[O7 >> 4];	*ptr++ = hexchars[O7 & 0xf];	*ptr++ = ':';	ptr = mem2hex((char *)&registers[O7], ptr, 4);	*ptr++ = ';';	*ptr++ = 0;	putpacket(remcomOutBuffer);	/* XXX We may want to add some features dealing with poking the	 * XXX page tables, the real ones on the srmmu, and what is currently	 * XXX loaded in the sun4/sun4c tlb at this point in time.  But this	 * XXX also required hacking to the gdb sources directly...	 */	while (1) {		remcomOutBuffer[0] = 0;		getpacket(remcomInBuffer);		switch (remcomInBuffer[0]) {		case '?':			remcomOutBuffer[0] = 'S';			remcomOutBuffer[1] = hexchars[sigval >> 4];			remcomOutBuffer[2] = hexchars[sigval & 0xf];			remcomOutBuffer[3] = 0;			break;		case 'd':			/* toggle debug flag */			break;		case 'g':		/* return the value of the CPU registers */		{			ptr = remcomOutBuffer;			/* G & O regs */			ptr = mem2hex((char *)registers, ptr, 16 * 4);			/* L & I regs */			ptr = mem2hex((char *) (sp + 0), ptr, 16 * 4);			/* Floating point */			memset(ptr, '0', 32 * 8);			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */			mem2hex((char *)&registers[Y], (ptr + 32 * 4 * 2), (8 * 4));		}			break;		case 'G':	   /* set the value of the CPU registers - return OK */		{			unsigned long *newsp, psr;			psr = registers[PSR];			ptr = &remcomInBuffer[1];			/* G & O regs */			hex2mem(ptr, (char *)registers, 16 * 4);			/* L & I regs */			hex2mem(ptr + 16 * 4 * 2, (char *) (sp + 0), 16 * 4);			/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */			hex2mem(ptr + 64 * 4 * 2, (char *)&registers[Y], 8 * 4);			/* See if the stack pointer has moved.  If so,			 * then copy the saved locals and ins to the			 * new location.  This keeps the window			 * overflow and underflow routines happy.			 */			newsp = (unsigned long *)registers[SP];			if (sp != newsp)				sp = memcpy(newsp, sp, 16 * 4);			/* Don't allow CWP to be modified. */			if (psr != registers[PSR])				registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f);			strcpy(remcomOutBuffer,"OK");		}			break;		case 'm':	  /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */			/* Try to read %x,%x.  */			ptr = &remcomInBuffer[1];			if (hexToInt(&ptr, &addr)			    && *ptr++ == ','			    && hexToInt(&ptr, &length))	{				if (mem2hex((char *)addr, remcomOutBuffer, length))					break;				strcpy (remcomOutBuffer, "E03");			} else {				strcpy(remcomOutBuffer,"E01");			}			break;		case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */			/* Try to read '%x,%x:'.  */			ptr = &remcomInBuffer[1];			if (hexToInt(&ptr, &addr)			    && *ptr++ == ','			    && hexToInt(&ptr, &length)			    && *ptr++ == ':') {				if (hex2mem(ptr, (char *)addr, length)) {					strcpy(remcomOutBuffer, "OK");				} else {					strcpy(remcomOutBuffer, "E03");				}			} else {				strcpy(remcomOutBuffer, "E02");			}			break;		case 'c':    /* cAA..AA    Continue at address AA..AA(optional) */			/* try to read optional parameter, pc unchanged if no parm */			ptr = &remcomInBuffer[1];			if (hexToInt(&ptr, &addr)) {				registers[PC] = addr;				registers[NPC] = addr + 4;			}/* 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. */			flush_cache_all();			unlock_kernel();			return;			/* kill the program */		case 'k' :		/* do nothing */			break;		case 'r':		/* Reset */			asm ("call 0\n\t"			     "nop\n\t");			break;		}			/* switch */		/* reply to the request */		putpacket(remcomOutBuffer);	} /* while(1) */}/* 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. */voidbreakpoint(void){	if (!initialized)		return;	/* Again, watch those c-prefixes for ELF kernels */#if defined(__svr4__) || defined(__ELF__)	asm(".globl breakinst\n"	    "breakinst:\n\t"	    "ta 1\n");#else	asm(".globl _breakinst\n"	    "_breakinst:\n\t"	    "ta 1\n");#endif}

⌨️ 快捷键说明

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