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
- Lines: 439
- Date:
Wed Dec 26 16:28:34 2001
- Orig file:
linux.orig/arch/ppc/xmon/xmon.c
- Orig date:
Mon Feb 18 20:18:39 2002
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)