📄 xmon.c
字号:
intbsesc(void){ int c; c = inchar(); switch( c ){ case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 'b': c = '\b'; break; case 't': c = '\t'; break; } return c;}#define isxdigit(c) (('0' <= (c) && (c) <= '9') \ || ('a' <= (c) && (c) <= 'f') \ || ('A' <= (c) && (c) <= 'F'))voiddump(void){ int c; c = inchar(); if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') termch = c; scanhex((void *)&adrs); if (termch != '\n') termch = 0; if (c == 'i') { scanhex(&nidump); if (nidump == 0) nidump = 16; else if (nidump > MAX_DUMP) nidump = MAX_DUMP; adrs += ppc_inst_dump(adrs, nidump, 1); last_cmd = "di\n"; } else { scanhex(&ndump); if (ndump == 0) ndump = 64; else if (ndump > MAX_DUMP) ndump = MAX_DUMP; prdump(adrs, ndump); adrs += ndump; last_cmd = "d\n"; }}voidprdump(unsigned long adrs, long ndump){ long n, m, c, r, nr; unsigned char temp[16]; for (n = ndump; n > 0;) { printf(REG, adrs); putchar(' '); r = n < 16? n: 16; nr = mread(adrs, temp, r); adrs += nr; for (m = 0; m < r; ++m) { if ((m & (sizeof(long) - 1)) == 0 && m > 0) putchar(' '); if (m < nr) printf("%.2x", temp[m]); else printf("%s", fault_chars[fault_type]); } for (; m < 16; ++m) { if ((m & (sizeof(long) - 1)) == 0) putchar(' '); printf(" "); } printf(" |"); for (m = 0; m < r; ++m) { if (m < nr) { c = temp[m]; putchar(' ' <= c && c <= '~'? c: '.'); } else putchar(' '); } n -= r; for (; m < 16; ++m) putchar(' '); printf("|\n"); if (nr < r) break; }}intppc_inst_dump(unsigned long adr, long count, int praddr){ int nr, dotted; unsigned long first_adr; unsigned long inst, last_inst = 0; unsigned char val[4]; dotted = 0; for (first_adr = adr; count > 0; --count, adr += 4) { nr = mread(adr, val, 4); if (nr == 0) { if (praddr) { const char *x = fault_chars[fault_type]; printf(REG" %s%s%s%s\n", adr, x, x, x, x); } break; } inst = GETWORD(val); if (adr > first_adr && inst == last_inst) { if (!dotted) { printf(" ...\n"); dotted = 1; } continue; } dotted = 0; last_inst = inst; if (praddr) printf(REG" %.8x", adr, inst); printf("\t"); print_insn_powerpc(inst, adr, 0); /* always returns 4 */ printf("\n"); } return adr - first_adr;}voidprint_address(unsigned long addr){ xmon_print_symbol(addr, "\t# ", "");}/* * Memory operations - move, set, print differences */static unsigned long mdest; /* destination address */static unsigned long msrc; /* source address */static unsigned long mval; /* byte value to set memory to */static unsigned long mcount; /* # bytes to affect */static unsigned long mdiffs; /* max # differences to print */voidmemops(int cmd){ scanhex((void *)&mdest); if( termch != '\n' ) termch = 0; scanhex((void *)(cmd == 's'? &mval: &msrc)); if( termch != '\n' ) termch = 0; scanhex((void *)&mcount); switch( cmd ){ case 'm': memmove((void *)mdest, (void *)msrc, mcount); break; case 's': memset((void *)mdest, mval, mcount); break; case 'd': if( termch != '\n' ) termch = 0; scanhex((void *)&mdiffs); memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs); break; }}voidmemdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr){ unsigned n, prt; prt = 0; for( n = nb; n > 0; --n ) if( *p1++ != *p2++ ) if( ++prt <= maxpr ) printf("%.16x %.2x # %.16x %.2x\n", p1 - 1, p1[-1], p2 - 1, p2[-1]); if( prt > maxpr ) printf("Total of %d differences\n", prt);}static unsigned mend;static unsigned mask;voidmemlocate(void){ unsigned a, n; unsigned char val[4]; last_cmd = "ml"; scanhex((void *)&mdest); if (termch != '\n') { termch = 0; scanhex((void *)&mend); if (termch != '\n') { termch = 0; scanhex((void *)&mval); mask = ~0; if (termch != '\n') termch = 0; scanhex((void *)&mask); } } n = 0; for (a = mdest; a < mend; a += 4) { if (mread(a, val, 4) == 4 && ((GETWORD(val) ^ mval) & mask) == 0) { printf("%.16x: %.16x\n", a, GETWORD(val)); if (++n >= 10) break; } }}static unsigned long mskip = 0x1000;static unsigned long mlim = 0xffffffff;voidmemzcan(void){ unsigned char v; unsigned a; int ok, ook; scanhex(&mdest); if (termch != '\n') termch = 0; scanhex(&mskip); if (termch != '\n') termch = 0; scanhex(&mlim); ook = 0; for (a = mdest; a < mlim; a += mskip) { ok = mread(a, &v, 1); if (ok && !ook) { printf("%.8x .. ", a); } else if (!ok && ook) printf("%.8x\n", a - mskip); ook = ok; if (a + mskip < a) break; } if (ook) printf("%.8x\n", a - mskip);}void proccall(void){ unsigned long args[8]; unsigned long ret; int i; typedef unsigned long (*callfunc_t)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); callfunc_t func; if (!scanhex(&adrs)) return; if (termch != '\n') termch = 0; for (i = 0; i < 8; ++i) args[i] = 0; for (i = 0; i < 8; ++i) { if (!scanhex(&args[i]) || termch == '\n') break; termch = 0; } func = (callfunc_t) adrs; ret = 0; if (setjmp(bus_error_jmp) == 0) { catch_memory_errors = 1; sync(); ret = func(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); sync(); printf("return value is %x\n", ret); } else { printf("*** %x exception occurred\n", fault_except); } catch_memory_errors = 0;}/* Input scanning routines */intskipbl(void){ int c; if( termch != 0 ){ c = termch; termch = 0; } else c = inchar(); while( c == ' ' || c == '\t' ) c = inchar(); return c;}#define N_PTREGS 44static char *regnames[N_PTREGS] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", "pc", "msr", "or3", "ctr", "lr", "xer", "ccr",#ifdef CONFIG_PPC64 "softe",#else "mq",#endif "trap", "dar", "dsisr", "res"};intscanhex(unsigned long *vp){ int c, d; unsigned long v; c = skipbl(); if (c == '%') { /* parse register name */ char regname[8]; int i; for (i = 0; i < sizeof(regname) - 1; ++i) { c = inchar(); if (!isalnum(c)) { termch = c; break; } regname[i] = c; } regname[i] = 0; for (i = 0; i < N_PTREGS; ++i) { if (strcmp(regnames[i], regname) == 0) { if (xmon_regs == NULL) { printf("regs not available\n"); return 0; } *vp = ((unsigned long *)xmon_regs)[i]; return 1; } } printf("invalid register name '%%%s'\n", regname); return 0; } /* skip leading "0x" if any */ if (c == '0') { c = inchar(); if (c == 'x') { c = inchar(); } else { d = hexdigit(c); if (d == EOF) { termch = c; *vp = 0; return 1; } } } else if (c == '$') { int i; for (i=0; i<63; i++) { c = inchar(); if (isspace(c)) { termch = c; break; } tmpstr[i] = c; } tmpstr[i++] = 0; *vp = 0; if (setjmp(bus_error_jmp) == 0) { catch_memory_errors = 1; sync(); *vp = kallsyms_lookup_name(tmpstr); sync(); } catch_memory_errors = 0; if (!(*vp)) { printf("unknown symbol '%s'\n", tmpstr); return 0; } return 1; } d = hexdigit(c); if (d == EOF) { termch = c; return 0; } v = 0; do { v = (v << 4) + d; c = inchar(); d = hexdigit(c); } while (d != EOF); termch = c; *vp = v; return 1;}voidscannl(void){ int c; c = termch; termch = 0; while( c != '\n' ) c = inchar();}int hexdigit(int c){ if( '0' <= c && c <= '9' ) return c - '0'; if( 'A' <= c && c <= 'F' ) return c - ('A' - 10); if( 'a' <= c && c <= 'f' ) return c - ('a' - 10); return EOF;}voidgetstring(char *s, int size){ int c; c = skipbl(); do { if( size > 1 ){ *s++ = c; --size; } c = inchar(); } while( c != ' ' && c != '\t' && c != '\n' ); termch = c; *s = 0;}static char line[256];static char *lineptr;voidflush_input(void){ lineptr = NULL;}intinchar(void){ if (lineptr == NULL || *lineptr == 0) { if (xmon_gets(line, sizeof(line)) == NULL) { lineptr = NULL; return EOF; } lineptr = line; } return *lineptr++;}voidtake_input(char *str){ lineptr = str;}static voidsymbol_lookup(void){ int type = inchar(); unsigned long addr; static char tmp[64]; switch (type) { case 'a': if (scanhex(&addr)) xmon_print_symbol(addr, ": ", "\n"); termch = 0; break; case 's': getstring(tmp, 64); if (setjmp(bus_error_jmp) == 0) { catch_memory_errors = 1; sync(); addr = kallsyms_lookup_name(tmp); if (addr) printf("%s: %lx\n", tmp, addr); else printf("Symbol '%s' not found.\n", tmp); sync(); } catch_memory_errors = 0; termch = 0; break; }}/* Print an address in numeric and symbolic form (if possible) */static void xmon_print_symbol(unsigned long address, const char *mid, const char *after){ char *modname; const char *name = NULL; unsigned long offset, size; printf(REG, address); if (setjmp(bus_error_jmp) == 0) { catch_memory_errors = 1; sync(); name = kallsyms_lookup(address, &size, &offset, &modname, tmpstr); sync(); /* wait a little while to see if we get a machine check */ __delay(200); } catch_memory_errors = 0; if (name) { printf("%s%s+%#lx/%#lx", mid, name, offset, size); if (modname) printf(" [%s]", modname); } printf("%s", after);}#ifdef CONFIG_PPC64static void dump_slb(void){ int i; unsigned long tmp; printf("SLB contents of cpu %x\n", smp_processor_id()); for (i = 0; i < SLB_NUM_ENTRIES; i++) { asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i)); printf("%02d %016lx ", i, tmp); asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i)); printf("%016lx\n", tmp); }}static void dump_stab(void){ int i; unsigned long *tmp = (unsigned long *)get_paca()->stab_addr; printf("Segment table contents of cpu %x\n", smp_processor_id()); for (i = 0; i < PAGE_SIZE/16; i++) { unsigned long a, b; a = *tmp++; b = *tmp++; if (a || b) { printf("%03d %016lx ", i, a); printf("%016lx\n", b); } }}void dump_segments(void){ if (cpu_has_feature(CPU_FTR_SLB)) dump_slb(); else dump_stab();}#endif#ifdef CONFIG_PPC_STD_MMU_32void dump_segments(void){ int i; printf("sr0-15 ="); for (i = 0; i < 16; ++i) printf(" %x", mfsrin(i)); printf("\n");}#endifvoid xmon_init(int enable){ if (enable) { __debugger = xmon; __debugger_ipi = xmon_ipi; __debugger_bpt = xmon_bpt; __debugger_sstep = xmon_sstep; __debugger_iabr_match = xmon_iabr_match; __debugger_dabr_match = xmon_dabr_match; __debugger_fault_handler = xmon_fault_handler; } else { __debugger = NULL; __debugger_ipi = NULL; __debugger_bpt = NULL; __debugger_sstep = NULL; __debugger_iabr_match = NULL; __debugger_dabr_match = NULL; __debugger_fault_handler = NULL; } xmon_map_scc();}#ifdef CONFIG_MAGIC_SYSRQstatic void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { /* ensure xmon is enabled */ xmon_init(1); debugger(pt_regs);}static struct sysrq_key_op sysrq_xmon_op = { .handler = sysrq_handle_xmon, .help_msg = "Xmon", .action_msg = "Entering xmon",};static int __init setup_xmon_sysrq(void){ register_sysrq_key('x', &sysrq_xmon_op); return 0;}__initcall(setup_xmon_sysrq);#endif /* CONFIG_MAGIC_SYSRQ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -