patch-2.4.18 linux/arch/ppc/xmon/xmon.c

Next file: linux/arch/s390/Makefile
Previous file: linux/arch/ppc/xmon/subr_prf.c
Back to the patch index
Back to the overall index

diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.xmon.c 1.16 09/22/01 15:25:10 trini
+ * BK Id: SCCS/s.xmon.c 1.18 12/01/01 20:09:07 benh
  */
 /*
  * Routines providing a simple monitor for use on the PowerMac.
@@ -90,6 +90,7 @@
 static void write_spr(int, unsigned);
 static void super_regs(void);
 static void print_sysmap(void);
+static void sysmap_lookup(void);
 static void remove_bpts(void);
 static void insert_bpts(void);
 static struct bpt *at_breakpoint(unsigned pc);
@@ -98,10 +99,7 @@
 #ifdef CONFIG_SMP
 static void cpu_cmd(void);
 #endif /* CONFIG_SMP */
-#if 0 /* Makes compile with -Wall */
-static char *pretty_print_addr(unsigned long addr);
-static char *lookup_name(unsigned long addr);
-#endif
+static int pretty_print_addr(unsigned long addr);
 static void csum(void);
 
 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
@@ -112,6 +110,8 @@
 
 extern void xmon_enter(void);
 extern void xmon_leave(void);
+extern char* xmon_find_symbol(unsigned long addr, unsigned long* saddr);
+extern unsigned long xmon_symbol_to_addr(char* symbol);
 
 #define GETWORD(v)	(((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
 
@@ -121,6 +121,7 @@
 #define isalnum(c)	(('0' <= (c) && (c) <= '9') \
 			 || ('a' <= (c) && (c) <= 'z') \
 			 || ('A' <= (c) && (c) <= 'Z'))
+#define isspace(c)	(c == ' ' || c == '\t' || c == 10 || c == 13 || c == 0)
 
 static char *help_string = "\
 Commands:\n\
@@ -138,6 +139,8 @@
   r	print registers\n\
   S	print special registers\n\
   t	print backtrace\n\
+  la	lookup address in system.map\n\
+  ls	lookup symbol in system.map\n\
   x	exit monitor\n\
 ";
 
@@ -147,6 +150,19 @@
 
 static struct pt_regs *xmon_regs[NR_CPUS];
 
+extern inline void sync(void)
+{
+	asm volatile("sync; isync");
+}
+
+extern inline void __delay(unsigned int loops)
+{
+	if (loops != 0)
+		__asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
+				     "r" (loops) : "ctr");
+}
+
+
 void
 xmon(struct pt_regs *excp)
 {
@@ -398,6 +414,9 @@
 		case 'd':
 			dump();
 			break;
+		case 'l':
+			sysmap_lookup();
+			break;
 		case 'r':
 			if (excp != NULL)
 				prregs(excp);	/* print regs */
@@ -464,8 +483,8 @@
 	if (cmd == 'i') {
 		/* interrupt other cpu(s) */
 		cpu = MSG_ALL_BUT_SELF;
-		scanhex(&cpu);
-		smp_send_xmon_break(cpu);
+		if (scanhex(&cpu))
+			smp_send_xmon_break(cpu);
 		return;
 	}
 	termch = cmd;
@@ -547,8 +566,10 @@
 	unsigned short fcs;
 	unsigned char v;
 
-	scanhex(&adrs);
-	scanhex(&ncsum);
+	if (!scanhex(&adrs))
+		return;
+	if (!scanhex(&ncsum))
+		return;
 	fcs = 0xffff;
 	for (i = 0; i < ncsum; ++i) {
 		if (mread(adrs+i, &v, 1) == 0) {
@@ -580,6 +601,11 @@
 			mode = 6;
 		else
 			termch = cmd;
+		cmd = inchar();
+		if (cmd == 'p')
+			mode &= ~4;
+		else
+			termch = cmd;
 		dabr.address = 0;
 		dabr.count = 0;
 		dabr.enabled = scanhex(&dabr.address);
@@ -588,11 +614,16 @@
 			dabr.address = (dabr.address & ~7) | mode;
 		break;
 	case 'i':
+		cmd = inchar();
+		if (cmd == 'p')
+			mode = 2;
+		else
+			mode = 3;
 		iabr.address = 0;
 		iabr.count = 0;
 		iabr.enabled = scanhex(&iabr.address);
 		if (iabr.enabled)
-			iabr.address |= 3;
+			iabr.address |= mode;
 		scanhex(&iabr.count);
 		break;
 #endif
@@ -625,6 +656,8 @@
 					printf("r");
 				if (dabr.address & 2)
 					printf("w");
+				if (dabr.address & 4)
+					printf("p");
 				printf("]\n");
 			}
 			if (iabr.enabled)
@@ -674,7 +707,8 @@
 	for (; sp != 0; sp = stack[0]) {
 		if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 			break;
-		printf("%x ", stack[1]);
+		pretty_print_addr(stack[1]);
+		printf(" ");
 		if (stack[1] == (unsigned) &ret_from_intercept
 		    || stack[1] == (unsigned) &ret_from_except
 		    || stack[1] == (unsigned) &ret_from_syscall_1
@@ -688,8 +722,8 @@
 			if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
 				break;
 		}
+		printf("\n");
 	}
-	printf("\n");
 }
 
 int
@@ -707,10 +741,11 @@
 #ifdef CONFIG_SMP
 	printf("cpu %d: ", smp_processor_id());
 #endif /* CONFIG_SMP */
-	printf("vector: %x at pc = %x",
-	       fp->trap, fp->nip);
-	printf(", lr = %x, msr = %x, sp = %x [%x]\n",
-	       fp->link, fp->msr, fp->gpr[1], fp);
+	printf("vector: %x at pc = ", fp->trap);
+	pretty_print_addr(fp->nip);
+	printf(", lr = ");
+	pretty_print_addr(fp->link);
+	printf("\nmsr = %x, sp = %x [%x]\n", fp->msr, fp->gpr[1], fp);
 	if (fp->trap == 0x300 || fp->trap == 0x600)
 		printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
 	if (current)
@@ -795,8 +830,16 @@
 print_sysmap(void)
 {
 	extern char *sysmap;
-	if ( sysmap )
-		printf("System.map: \n%s", sysmap);
+	if ( sysmap ) {
+		printf("System.map: \n");
+		if( setjmp(bus_error_jmp) == 0 ) {
+			debugger_fault_handler = handle_fault;
+			sync();
+			xmon_puts(sysmap);
+			sync();
+		}
+		debugger_fault_handler = 0;
+	}
 	else
 		printf("No System.map\n");
 }
@@ -1028,17 +1071,6 @@
 /*
  * Stuff for reading and writing memory safely
  */
-extern inline void sync(void)
-{
-	asm volatile("sync; isync");
-}
-
-extern inline void __delay(unsigned int loops)
-{
-	if (loops != 0)
-		__asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
-				     "r" (loops) : "ctr");
-}
 
 int
 mread(unsigned adrs, void *buf, int size)
@@ -1565,6 +1597,24 @@
 		}
 		printf("invalid register name '%%%s'\n", regname);
 		return 0;
+	} else if (c == '$') {
+		static char symname[64];
+		int i;
+		for (i=0; i<63; i++) {
+			c = inchar();
+			if (isspace(c)) {
+				termch = c;
+				break;
+			}
+			symname[i] = c;
+		}
+		symname[i++] = 0;
+		*vp = xmon_symbol_to_addr(symname);
+		if (!(*vp)) {
+			printf("unknown symbol\n");
+			return 0;
+		}
+		return 1;
 	}
 
 	d = hexdigit(c);
@@ -1652,38 +1702,169 @@
 	lineptr = str;
 }
 
-#if 0 /* Makes compile with -Wall */
-static char *pretty_print_addr(unsigned long addr)
+void
+sysmap_lookup(void)
 {
-	printf("%08x", addr);
-	if ( lookup_name(addr) )
-		printf(" %s", lookup_name(addr) );
-	return NULL;
+	int type = inchar();
+	unsigned addr;
+	static char tmp[64];
+	char* cur;
+
+	extern char *sysmap;
+	extern unsigned long sysmap_size;
+	if ( !sysmap || !sysmap_size )
+		return;
+
+	switch(type) {
+		case 'a':
+			if (scanhex(&addr)) {
+				pretty_print_addr(addr);
+				printf("\n");
+			}
+			termch = 0;
+			break;
+		case 's':
+			getstring(tmp, 64);
+			if( setjmp(bus_error_jmp) == 0 ) {
+				debugger_fault_handler = handle_fault;
+				sync();
+				cur = sysmap;
+				do {
+					cur = strstr(cur, tmp);
+					if (cur) {
+						static char res[64];
+						char *p, *d;
+						p = cur;
+						while(p > sysmap && *p != 10)
+							p--;
+						if (*p == 10) p++;
+						d = res;
+						while(*p && p < (sysmap + sysmap_size) && *p != 10)
+							*(d++) = *(p++);
+						*(d++) = 0;
+						printf("%s\n", res);
+						cur++;
+					}
+				} while (cur);
+				sync();
+			}
+			debugger_fault_handler = 0;
+			termch = 0;
+			break;
+	}
 }
-#endif
 
-#if 0 /* Makes compile with -Wall */
-static char *lookup_name(unsigned long addr)
+static int
+pretty_print_addr(unsigned long addr)
 {
+	char *sym;
+	unsigned long saddr;
+	
+	printf("%08x", addr);
+	sym = xmon_find_symbol(addr, &saddr);
+	if (sym)
+		printf(" (%s+0x%x)", sym, addr-saddr);
+	return (sym != 0);
+}
+
+char*
+xmon_find_symbol(unsigned long addr, unsigned long* saddr)
+{
+	static char rbuffer[64];
+	char *p, *ep, *limit;
+	unsigned long prev, next;
+	char* psym;
+
 	extern char *sysmap;
 	extern unsigned long sysmap_size;
-	char *c = sysmap;
-	unsigned long cmp;
 	if ( !sysmap || !sysmap_size )
 		return NULL;
-return NULL;	
-#if 0
-	cmp = simple_strtoul(c, &c, 8);
-	/* XXX crap, we don't want the whole of the rest of the map - paulus */
-	strcpy( last, strsep( &c, "\n"));
-	while ( c < (sysmap+sysmap_size) )
-	{
-		cmp = simple_strtoul(c, &c, 8);
-		if ( cmp < addr )
-			break;
-		strcpy( last, strsep( &c, "\n"));
+	
+	prev = 0;
+	psym = NULL;
+	p = sysmap;
+	limit = p + sysmap_size;
+	if( setjmp(bus_error_jmp) == 0 ) {
+		debugger_fault_handler = handle_fault;
+		sync();
+		do {
+			next = simple_strtoul(p, &p, 16);
+			if (next > addr && prev <= addr) {
+				if (!psym)
+					goto bail;
+				ep = rbuffer;
+				p = psym;
+				while(*p && p < limit && *p == 32)
+					p++;
+				while(*p && p < limit && *p != 10 && (ep - rbuffer) < 63)
+					*(ep++) = *(p++);
+				*(ep++) = 0;
+				if (saddr)
+					*saddr = prev;
+				debugger_fault_handler = 0;
+				return rbuffer;
+			}
+			prev = next;
+			psym = p;
+			while(*p && p < limit && *p != 10)
+				p++;
+			if (*p) p++;
+		} while(*p && p < limit && next);
+bail:
+		sync();
 	}
-	return last;
-#endif	
+	debugger_fault_handler = 0;
+	return NULL;
 }
-#endif
+
+unsigned long
+xmon_symbol_to_addr(char* symbol)
+{
+	char *p, *cur;
+	char *match;
+	int goodness = 0;
+	int result = 0;
+	
+	extern char *sysmap;
+	extern unsigned long sysmap_size;
+	if ( !sysmap || !sysmap_size )
+		return 0;
+
+	if( setjmp(bus_error_jmp) == 0 ) {
+		debugger_fault_handler = handle_fault;
+		sync();
+		cur = sysmap;
+		while(cur) {
+			cur = strstr(cur, symbol);
+			if (cur) {
+				int gd = 1;
+
+				/* best match if equal, better match if
+				 * begins with
+				 */
+				if (cur == sysmap || *(cur-1) == ' ') {
+					gd++;
+					if (cur[strlen(symbol)] == 10)
+						gd++;
+				}
+				if (gd > goodness) {
+					match = cur;
+					goodness = gd;
+					if (gd == 3)
+						break;
+				}
+				cur++;
+			}
+		}	
+		if (goodness) {
+			p = match;
+			while(p > sysmap && *p != 10)
+				p--;
+			if (*p == 10) p++;
+			result = simple_strtoul(p, &p, 16);
+		}
+		sync();
+	}
+	debugger_fault_handler = 0;
+	return result;
+}		

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)