int kdb_rm(int argc, const char **argv, const char **envp, struct pt_regs *regs) { int diag; int ind = 0; unsigned long contents; if (argc != 2) { return KDB_ARGCOUNT; } /* * Allow presence or absence of leading '%' symbol. */ if (argv[1][0] == '%') ind = 1; diag = kdbgetularg(argv[2], &contents); if (diag) return diag; diag = kdbsetregcontents(&argv[1][ind], regs, contents); if (diag) return diag; return 0; }
int kdb_ll(int argc, const char **argv, const char **envp, struct pt_regs *regs) { int diag; unsigned long addr, firstaddr; long offset = 0; unsigned long va; unsigned long linkoffset; int nextarg; if (argc != 3) { return KDB_ARGCOUNT; } nextarg = 1; diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs); if (diag) return diag; diag = kdbgetularg(argv[2], &linkoffset); if (diag) return diag; /* * Using the starting address as the first element in the list, * and assuming that the list ends with a null pointer or with * the first element again (do the right thing for both * null-terminated and circular lists). */ va = firstaddr = addr; while (va) { char buf[80]; sprintf(buf, "%s 0x%lx\n", argv[3], va); diag = kdb_parse(buf, regs); if (diag) return diag; addr = va + linkoffset; va = kdbgetword(addr, sizeof(va)); if (kdb_flags & KDB_FLAG_SUPRESS) { kdb_flags &= ~KDB_FLAG_SUPRESS; return 0; } if (va == firstaddr) break; } return 0; }
static int kdbm_vm(int argc, const char **argv) { unsigned long addr; long offset = 0; int nextarg; int diag; int verbose_flg = 0; if (argc == 2) { if (strcmp(argv[1], "-v") != 0) { return KDB_ARGCOUNT; } verbose_flg = 1; } else if (argc != 1) { return KDB_ARGCOUNT; } if (strcmp(argv[0], "vmp") == 0) { struct task_struct *g, *tp; struct vm_area_struct *vp; pid_t pid; if ((diag = kdbgetularg(argv[argc], (unsigned long *) &pid))) return diag; kdb_do_each_thread(g, tp) { if (tp->pid == pid) { if (tp->mm != NULL) { if (verbose_flg) kdb_printf ("vm_area_struct "); kdb_printf ("vm_start vm_end vm_flags\n"); vp = tp->mm->mmap; while (vp != NULL) { kdbm_print_vmp(vp, verbose_flg); vp = vp->vm_next; } } return 0; } } kdb_while_each_thread(g, tp); kdb_printf("No process with pid == %d found\n", pid); } else {
static int kdb_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp) { int nextarg = *nextargp; int diag; bp->bph_length = 1; if ((argc + 1) != nextarg) { if (strncasecmp(argv[nextarg], "datar", sizeof("datar")) == 0) bp->bp_type = BP_ACCESS_WATCHPOINT; else if (strncasecmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) bp->bp_type = BP_WRITE_WATCHPOINT; else if (strncasecmp(argv[nextarg], "inst", sizeof("inst")) == 0) bp->bp_type = BP_HARDWARE_BREAKPOINT; else return KDB_ARGCOUNT; bp->bph_length = 1; nextarg++; if ((argc + 1) != nextarg) { unsigned long len; diag = kdbgetularg((char *)argv[nextarg], &len); if (diag) return diag; if (len > 8) return KDB_BADLENGTH; bp->bph_length = len; nextarg++; } if ((argc + 1) != nextarg) return KDB_ARGCOUNT; } *nextargp = nextarg; return 0; }
int kdb_cpu(int argc, const char **argv, const char **envp, struct pt_regs *regs) { unsigned long cpunum; int diag; if (argc == 0) { int i; kdb_printf("Currently on cpu %d\n", smp_processor_id()); kdb_printf("Available cpus: "); for (i=0; i<NR_CPUS; i++) { if (test_bit(i, &cpu_online_map)) { if (i) kdb_printf(", "); kdb_printf("%d", i); } } kdb_printf("\n"); return 0; } if (argc != 1) return KDB_ARGCOUNT; diag = kdbgetularg(argv[1], &cpunum); if (diag) return diag; /* * Validate cpunum */ if ((cpunum > NR_CPUS) || !test_bit(cpunum, &cpu_online_map)) return KDB_BADCPUNUM; kdb_new_cpu = cpunum; /* * Switch to other cpu */ return KDB_CPUSWITCH; }
int kdb_md(int argc, const char **argv, const char **envp, struct pt_regs *regs) { char fmtchar; char fmtstr[64]; int radix, count, width; unsigned long addr; unsigned long word; long offset = 0; int diag; int nextarg; static unsigned long lastaddr = 0; static unsigned long lastcount = 0; static unsigned long lastradix = 0; char lastbuf[50]; int symbolic = 0; /* * Defaults in case the relevent environment variables are unset */ radix = 16; count = 8; width = 4; if (argc == 0) { if (lastaddr == 0) return KDB_ARGCOUNT; sprintf(lastbuf, "0x%lx", lastaddr); argv[1] = lastbuf; argc = 1; count = lastcount; radix = lastradix; } else { unsigned long val; if (argc >= 2) { diag = kdbgetularg(argv[2], &val); if (!diag) count = (int) val; } else { diag = kdbgetintenv("MDCOUNT", &count); } if (argc >= 3) { diag = kdbgetularg(argv[3], &val); if (!diag) radix = (int) val; } else { diag = kdbgetintenv("RADIX",&radix); } } switch (radix) { case 10: fmtchar = 'd'; break; case 16: fmtchar = 'x'; break; case 8: fmtchar = 'o'; break; default: return KDB_BADRADIX; } diag = kdbgetintenv("BYTESPERWORD", &width); if (strcmp(argv[0], "mds") == 0) { symbolic = 1; width = 4; } switch (width) { case 4: sprintf(fmtstr, "%%8.8%c ", fmtchar); break; case 2: sprintf(fmtstr, "%%4.4%c ", fmtchar); break; case 1: sprintf(fmtstr, "%%2.2%c ", fmtchar); break; default: return KDB_BADWIDTH; } nextarg = 1; diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs); if (diag) return diag; /* Round address down modulo BYTESPERWORD */ addr &= ~(width-1); /* * Remember count and radix for next 'md' */ lastcount = count; lastradix = radix; while (count--) { int num = (symbolic?1 :(16 / width)); char cbuf[32]; char *c = cbuf; char t; int i; for(i=0; i<sizeof(cbuf); i++) { cbuf[i] = '\0'; } kdb_printf("%8.8x: ", addr); for(i=0; i<num; i++) { char *name = NULL; word = kdbgetword(addr, width); if (kdb_flags & KDB_FLAG_SUPRESS) { kdb_flags &= ~KDB_FLAG_SUPRESS; return 0; /* Error message already printed */ } kdb_printf(fmtstr, word); if (symbolic) { name = kdbnearsym(word); } if (name) { unsigned long offset; offset = word - kdbgetsymval(name); kdb_printf("%s+0x%x", name, offset); addr += 4; } else { switch (width) { case 4: *c++ = isprint(t=kdbgetword(addr++, 1)) ?t:'.'; *c++ = isprint(t=kdbgetword(addr++, 1)) ?t:'.'; case 2: *c++ = isprint(t=kdbgetword(addr++, 1)) ?t:'.'; case 1: *c++ = isprint(t=kdbgetword(addr++, 1)) ?t:'.'; break; } } } kdb_printf(" %s\n", cbuf); } lastaddr = addr; return 0; }
int kdbgetaddrarg(int argc, const char **argv, int *nextarg, unsigned long *value, long *offset, char **name, struct pt_regs *regs) { unsigned long addr; long off = 0; int positive; int diag; char *symname; char symbol = '\0'; char *cp; /* * Process arguments which follow the following syntax: * * symbol | numeric-address [+/- numeric-offset] * %register * $environment-variable */ if (*nextarg > argc) { return KDB_ARGCOUNT; } symname = (char *)argv[*nextarg]; /* * If there is no whitespace between the symbol * or address and the '+' or '-' symbols, we * remember the character and replace it with a * null so the symbol/value can be properly parsed */ if ((cp = strpbrk(symname, "+-")) != NULL) { symbol = *cp; *cp++ = '\0'; } if (symname[0] == '$') { diag = kdbgetulenv(&symname[1], &addr); if (diag) return diag; } else if (symname[0] == '%') { diag = kdbgetregcontents(&symname[1], regs, &addr); if (diag) return diag; } else { addr = kdbgetsymval(symname); if (addr == 0) { diag = kdbgetularg(argv[*nextarg], &addr); if (diag) return diag; } } symname = kdbnearsym(addr); (*nextarg)++; if (name) *name = symname; if (value) *value = addr; if (offset && name && *name) *offset = addr - kdbgetsymval(*name); if ((*nextarg > argc) && (symbol == '\0')) return 0; /* * check for +/- and offset */ if (symbol == '\0') { if ((argv[*nextarg][0] != '+') && (argv[*nextarg][0] != '-')) { /* * Not our argument. Return. */ return 0; } else { positive = (argv[*nextarg][0] == '+'); (*nextarg)++; } } else positive = (symbol == '+'); /* * Now there must be an offset! */ if ((*nextarg > argc) && (symbol == '\0')) { return KDB_INVADDRFMT; } if (!symbol) { cp = (char *)argv[*nextarg]; (*nextarg)++; } diag = kdbgetularg(cp, &off); if (diag) return diag; if (!positive) off = -off; if (offset) *offset += off; if (value) *value += off; return 0; }
int kdba_parsebp(int argc, const char **argv, int *nextargp, kdb_bp_t *bp) { int nextarg = *nextargp; int diag; kdbhard_bp_t *bph = &bp->bp_template; bph->bph_mode = 0; /* Default to instruction breakpoint */ bph->bph_length = 0; /* Length must be zero for insn bp */ if ((argc + 1) != nextarg) { if (strnicmp(argv[nextarg], "datar", sizeof("datar")) == 0) { bph->bph_mode = 3; } else if (strnicmp(argv[nextarg], "dataw", sizeof("dataw")) == 0) { bph->bph_mode = 1; } else if (strnicmp(argv[nextarg], "io", sizeof("io")) == 0) { bph->bph_mode = 2; } else if (strnicmp(argv[nextarg], "inst", sizeof("inst")) == 0) { bph->bph_mode = 0; } else { return KDB_ARGCOUNT; } bph->bph_length = 3; /* Default to 4 byte */ nextarg++; if ((argc + 1) != nextarg) { unsigned long len; diag = kdbgetularg((char *)argv[nextarg], &len); if (diag) return diag; if ((len > 4) || (len == 3)) return KDB_BADLENGTH; bph->bph_length = len; bph->bph_length--; /* Normalize for debug register */ nextarg++; } if ((argc + 1) != nextarg) return KDB_ARGCOUNT; /* * Indicate to architecture independent level that * a hardware register assignment is required to enable * this breakpoint. */ bph->bph_free = 0; } else { if (KDB_DEBUG(BP)) kdb_printf("kdba_bp: no args, forcehw is %d\n", bp->bp_forcehw); if (bp->bp_forcehw) { /* * We are forced to use a hardware register for this * breakpoint because either the bph or bpha * commands were used to establish this breakpoint. */ bph->bph_free = 0; } else { /* * Indicate to architecture dependent level that * the instruction replacement breakpoint technique * should be used for this breakpoint. */ bph->bph_free = 1; bp->bp_adjust = 1; /* software, int 3 is one byte */ } } if (bph->bph_mode != 2 && kdba_verify_rw(bp->bp_addr, bph->bph_length+1)) { kdb_printf("Invalid address for breakpoint, ignoring bp command\n"); return KDB_BADADDR; } *nextargp = nextarg; return 0; }
int kdb_bt(int argc, const char **argv, const char **envp, struct pt_regs *regs) { int done = 0; #if !defined(CONFIG_KDB_FRAMEPTR) unsigned long sp; #endif unsigned long base, limit, esp, ebp, eip; unsigned long start = 0; /* Start address of current function */ unsigned long addr; long offset = 0; int nextarg; int argcount=5; char *name; int diag; struct pt_regs taskregs; struct frame { unsigned long ebp; unsigned long eip; } old; unsigned long stackbase = (unsigned long)current; /* * Determine how many possible arguments to print. */ diag = kdbgetintenv("BTARGS", &argcount); if (strcmp(argv[0], "btp") == 0){ struct task_struct *p; int pid; diag = kdbgetularg((char *)argv[1], (unsigned long*)&pid); if (diag) return diag; taskregs.eax = 1; for_each_task(p) { if (p->pid == pid) { taskregs.eip = p->tss.eip; taskregs.esp = p->tss.esp; taskregs.ebp = p->tss.ebp; /* * Since we don't really use the TSS * to store register between task switches, * attempt to locate real ebp (should be * top of stack if task is in schedule) */ if (taskregs.ebp == 0) { taskregs.ebp = *(unsigned long *)(taskregs.esp); } taskregs.eax = 0; stackbase = (unsigned long)p; break; } } if (taskregs.eax == 1) { kdb_printf("No process with pid == %d found\n", pid); return 0; } regs = &taskregs; } else { if (argc) {
static int kdb_bc(int argc, const char **argv) { kdb_machreg_t addr; kdb_bp_t *bp = NULL; int lowbp = KDB_MAXBPT; int highbp = 0; int done = 0; int i; int diag; int cmd; /* KDBCMD_B? */ if (strcmp(argv[0], "be") == 0) { cmd = KDBCMD_BE; } else if (strcmp(argv[0], "bd") == 0) { cmd = KDBCMD_BD; } else cmd = KDBCMD_BC; if (argc != 1) return KDB_ARGCOUNT; if (strcmp(argv[1], "*") == 0) { lowbp = 0; highbp = KDB_MAXBPT; } else { diag = kdbgetularg(argv[1], &addr); if (diag) return diag; /* * For addresses less than the maximum breakpoint number, * assume that the breakpoint number is desired. */ if (addr < KDB_MAXBPT) { bp = &kdb_breakpoints[addr]; lowbp = highbp = addr; highbp++; } else { for(i=0, bp=kdb_breakpoints; i<KDB_MAXBPT; i++, bp++) { if (bp->bp_addr == addr) { lowbp = highbp = i; highbp++; break; } } } } /* * Now operate on the set of breakpoints matching the input * criteria (either '*' for all, or an individual breakpoint). */ for(bp=&kdb_breakpoints[lowbp], i=lowbp; i < highbp; i++, bp++) { if (bp->bp_free) continue; done++; switch (cmd) { case KDBCMD_BC: if (bp->bp_hardtype) kdba_free_hwbp(bp); bp->bp_enabled = 0; bp->bp_global = 0; kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " cleared\n", i, bp->bp_addr); bp->bp_addr = 0; bp->bp_free = 1; break; case KDBCMD_BE: /* * Allocate a hardware breakpoint. If one is not * available, don't enable the breakpoint. */ if (!bp->bp_template.bph_free && !bp->bp_hardtype) { kdba_alloc_hwbp(bp, &diag); if (diag) { bp->bp_enabled = 0; bp->bp_hardtype = 0; kdba_free_hwbp(bp); return diag; } } bp->bp_enabled = 1; kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " enabled", i, bp->bp_addr); kdb_printf("\n"); break; case KDBCMD_BD: if (!bp->bp_enabled) break; /* * Since this breakpoint is now disabled, we can * give up the hardware register which is allocated * to it. */ if (bp->bp_hardtype) kdba_free_hwbp(bp); bp->bp_enabled = 0; kdb_printf("Breakpoint %d at " kdb_bfd_vma_fmt " disabled\n", i, bp->bp_addr); break; } if (bp->bp_delay && (cmd == KDBCMD_BC || cmd == KDBCMD_BD)) { bp->bp_delay = 0; KDB_STATE_CLEAR(SSBPT); } } return (!done)?KDB_BPTNOTFOUND:0; }