📄 xmon.c
字号:
case '<': n = size; scanhex(&n); adrs -= n; break; case '>': n = size; scanhex(&n); adrs += n; break; case '?': printf(memex_subcmd_help_string); break; } } adrs += inc; }}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("%.16lx", adrs); putchar(' '); r = n < 16? n: 16; nr = mread(adrs, temp, r); adrs += nr; for (m = 0; m < r; ++m) { if ((m & 7) == 0 && m > 0) putchar(' '); if (m < nr) printf("%.2x", temp[m]); else printf("%s", fault_chars[fault_type]); } if (m <= 8) printf(" "); for (; m < 16; ++m) 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("%.16lx %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("%.16lx %.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); fflush(stdout); } else if (!ok && ook) printf("%.8x\n", a - mskip); ook = ok; if (a + mskip < a) break; } if (ook) printf("%.8x\n", a - mskip);}/* 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", "softe", "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();}inthexdigit(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 (fgets(line, sizeof(line), stdin) == 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("%.16lx", 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);}static void debug_trace(void){ unsigned long val, cmd, on; cmd = skipbl(); if (cmd == '\n') { /* show current state */ unsigned long i; printf("ppc64_debug_switch = 0x%lx\n", ppc64_debug_switch); for (i = 0; i < PPCDBG_NUM_FLAGS ;i++) { on = PPCDBG_BITVAL(i) & ppc64_debug_switch; printf("%02x %s %12s ", i, on ? "on " : "off", trace_names[i] ? trace_names[i] : ""); if (((i+1) % 3) == 0) printf("\n"); } printf("\n"); return; } while (cmd != '\n') { on = 1; /* default if no sign given */ while (cmd == '+' || cmd == '-') { on = (cmd == '+'); cmd = inchar(); if (cmd == ' ' || cmd == '\n') { /* Turn on or off based on + or - */ ppc64_debug_switch = on ? PPCDBG_ALL:PPCDBG_NONE; printf("Setting all values to %s...\n", on ? "on" : "off"); if (cmd == '\n') return; else cmd = skipbl(); } else termch = cmd; } termch = cmd; /* not +/- ... let scanhex see it */ scanhex((void *)&val); if (val >= 64) { printf("Value %x out of range:\n", val); return; } if (on) { ppc64_debug_switch |= PPCDBG_BITVAL(val); printf("enable debug %x %s\n", val, trace_names[val] ? trace_names[val] : ""); } else { ppc64_debug_switch &= ~PPCDBG_BITVAL(val); printf("disable debug %x %s\n", val, trace_names[val] ? trace_names[val] : ""); } cmd = skipbl(); }}static 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 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; }}void dump_segments(void){ if (cpu_has_feature(CPU_FTR_SLB)) dump_slb(); else dump_stab();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -