int kdb_mm(int argc, const char **argv, const char **envp, struct pt_regs *regs) { int diag; unsigned long addr; long offset = 0; unsigned long contents; unsigned long word; int nextarg; if (argc != 2) { return KDB_ARGCOUNT; } nextarg = 1; diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs); if (diag) return diag; if (nextarg > argc) return KDB_ARGCOUNT; diag = kdbgetaddrarg(argc, argv, &nextarg, &contents, NULL, NULL, regs); if (diag) return diag; if (nextarg != argc + 1) return KDB_ARGCOUNT; /* * To prevent modification of invalid addresses, check first. */ word = kdbgetword(addr, sizeof(word)); if (kdb_flags & KDB_FLAG_SUPRESS) { kdb_flags &= ~KDB_FLAG_SUPRESS; return 0; } *(unsigned long *)(addr) = contents; kdb_printf("0x%x = 0x%x\n", addr, contents); 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_sigset(int argc, const char **argv) { sigset_t *sp = NULL; unsigned long addr; long offset=0; int nextarg; int e = 0; int i; char fmt[32]; if (argc != 1) return KDB_ARGCOUNT; #ifndef _NSIG_WORDS kdb_printf("unavailable on this platform, _NSIG_WORDS not defined.\n"); #else nextarg = 1; if ((e = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL)) != 0) return(e); if (!(sp = kmalloc(sizeof(*sp), GFP_ATOMIC))) { kdb_printf("%s: cannot kmalloc sp\n", __FUNCTION__); goto out; } if ((e = kdb_getarea(*sp, addr))) { kdb_printf("%s: invalid sigset address\n", __FUNCTION__); goto out; } sprintf(fmt, "[%%d]=0x%%0%dlx ", (int)sizeof(sp->sig[0])*2); kdb_printf("sigset at 0x%p : ", sp); for (i=_NSIG_WORDS-1; i >= 0; i--) { if (i == 0 || sp->sig[i]) { kdb_printf(fmt, i, sp->sig[i]); } } kdb_printf("\n"); #endif /* _NSIG_WORDS */ out: if (sp) kfree(sp); return e; }
int kdb_go(int argc, const char **argv, const char **envp, struct pt_regs *regs) { unsigned long addr; int diag; int nextarg; long offset; if (argc == 1) { nextarg = 1; diag = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL, regs); if (diag) return diag; regs->eip = addr; } else if (argc) return KDB_ARGCOUNT; return KDB_GO; }
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; }
static int kdb_parse(char *cmdstr, struct pt_regs *regs) { char *argv[MAXARGC]; int argc=0; char *cp; kdbtab_t *tp; int i; /* * First tokenize the command string. */ cp = cmdstr; /* * If a null statement is provided, do nothing. */ if ((*cp == '\n') || (*cp == '\0')) return 0; while (*cp) { /* skip whitespace */ while (isspace(*cp)) cp++; if ((*cp == '\0') || (*cp == '\n')) break; argv[argc++] = cp; /* Skip to next whitespace */ for(; *cp && (!isspace(*cp) && (*cp != '=')); cp++); *cp++ = '\0'; /* Squash a ws or '=' character */ } for(tp=kdb_commands, i=0; i < KDB_MAX_COMMANDS; i++,tp++) { if (tp->cmd_name) { /* * If this command is allowed to be abbreviated, * check to see if this is it. */ if (tp->cmd_minlen && (strlen(argv[0]) <= tp->cmd_minlen)) { if (strncmp(argv[0], tp->cmd_name, tp->cmd_minlen) == 0) { break; } } if (strcmp(argv[0], tp->cmd_name)==0) { break; } } } if (i < KDB_MAX_COMMANDS) { return (*tp->cmd_func)(argc-1, (const char**)argv, (const char**)__env, regs); } /* * If the input with which we were presented does not * map to an existing command, attempt to parse it as an * address argument and display the result. Useful for * obtaining the address of a variable, or the nearest symbol * to an address contained in a register. */ { unsigned long value; char *name = NULL; long offset; int nextarg = 0; if (kdbgetaddrarg(0, (const char **)argv, &nextarg, &value, &offset, &name, regs)) { return KDB_NOTFOUND; } kdb_printf("%s = 0x%8.8x ", argv[0], value); if (name) { kdb_printf("(%s+0x%lx)", name, offset); } kdb_printf("\n"); return 0; } }
int kdb_id(int argc, const char **argv) { kdb_machreg_t pc; int icount; int diag; int i; char *mode; int nextarg; long offset = 0; static kdb_machreg_t lastpc; struct disassemble_info *dip = &kdb_di; char lastbuf[50]; unsigned long word; kdb_di.fprintf_func = kdb_dis_fprintf; kdba_id_init(&kdb_di); if (argc != 1) { if (lastpc == 0) { return KDB_ARGCOUNT; } else { sprintf(lastbuf, "0x%lx", lastpc); argv[1] = lastbuf; argc = 1; } } /* * Fetch PC. First, check to see if it is a symbol, if not, * try address. */ nextarg = 1; diag = kdbgetaddrarg(argc, argv, &nextarg, &pc, &offset, NULL); if (diag) return diag; kdba_check_pc(&pc); if (kdb_getarea(word, pc)) return(0); /* * Number of lines to display */ diag = kdbgetintenv("IDCOUNT", &icount); if (diag) return diag; mode = kdbgetenv("IDMODE"); diag = kdba_id_parsemode(mode, dip); if (diag) { return diag; } for(i=0; i<icount; i++) { pc += kdba_id_printinsn(pc, &kdb_di); kdb_printf("\n"); } lastpc = pc; return 0; }
static int kdbm_task(int argc, const char **argv) { unsigned long addr; long offset=0; int nextarg; int e = 0; struct task_struct *tp = NULL, *tp1; if (argc != 1) return KDB_ARGCOUNT; nextarg = 1; if ((e = kdbgetaddrarg(argc, argv, &nextarg, &addr, &offset, NULL)) != 0) return(e); if (!(tp = kmalloc(sizeof(*tp), GFP_ATOMIC))) { kdb_printf("%s: cannot kmalloc tp\n", __FUNCTION__); goto out; } if ((e = kdb_getarea(*tp, addr))) { kdb_printf("%s: invalid task address\n", __FUNCTION__); goto out; } tp1 = (struct task_struct *)addr; kdb_printf( "struct task at 0x%lx, pid=%d flags=0x%x state=%ld comm=\"%s\"\n", addr, tp->pid, tp->flags, tp->state, tp->comm); kdb_printf(" cpu=%d policy=%u ", kdb_process_cpu(tp), tp->policy); kdb_printf( "prio=%d static_prio=%d cpus_allowed=", tp->prio, tp->static_prio); { /* The cpus allowed string may be longer than kdb_printf() can * handle. Print it in chunks. */ char c, *p; p = kdb_cpus_allowed_string(tp); while (1) { if (strlen(p) < 100) { kdb_printf("%s", p); break; } c = p[100]; p[100] = '\0'; kdb_printf("%s", p); p[100] = c; p += 100; } } kdb_printf(" &thread=0x%p\n", &tp1->thread); kdb_printf(" need_resched=%d ", test_tsk_thread_flag(tp, TIF_NEED_RESCHED)); kdb_printf( "timestamp=%llu time_slice=%u", tp->timestamp, tp->time_slice); kdb_printf(" lock_depth=%d\n", tp->lock_depth); kdb_printf( " fs=0x%p files=0x%p mm=0x%p\n", tp->fs, tp->files, tp->mm); kdb_printf( " uid=%d euid=%d suid=%d fsuid=%d gid=%d egid=%d sgid=%d fsgid=%d\n", tp->uid, tp->euid, tp->suid, tp->fsuid, tp->gid, tp->egid, tp->sgid, tp->fsgid); kdb_printf( " user=0x%p\n", tp->user); if (tp->sysvsem.undo_list) kdb_printf( " sysvsem.sem_undo refcnt %d proc_list=0x%p\n", atomic_read(&tp->sysvsem.undo_list->refcnt), tp->sysvsem.undo_list->proc_list); kdb_printf( " signal=0x%p &blocked=0x%p &pending=0x%p\n", tp->signal, &tp1->blocked, &tp1->pending); kdb_printf( " utime=%ld stime=%ld cutime=%ld cstime=%ld\n", tp->utime, tp->stime, tp->signal ? tp->signal->cutime : 0L, tp->signal ? tp->signal->cstime : 0L); kdb_printf(" thread_info=0x%p\n", task_thread_info(tp)); kdb_printf(" ti flags=0x%lx\n", (unsigned long)task_thread_info(tp)->flags); out: if (tp) kfree(tp); return e; }
static int kdb_bp(int argc, const char **argv) { int i, bpno; kdb_bp_t *bp, *bp_check; int diag; int free; char *symname = NULL; long offset = 0ul; int nextarg; static kdb_bp_t kdb_bp_template; if (argc == 0) { /* * Display breakpoint table */ for(bpno=0,bp=kdb_breakpoints; bpno<KDB_MAXBPT; bpno++, bp++) { if (bp->bp_free) continue; kdb_printbp(bp, bpno); } return 0; } memset(&kdb_bp_template, 0, sizeof(kdb_bp_template)); kdb_bp_template.bp_global = ((strcmp(argv[0], "bpa") == 0) || (strcmp(argv[0], "bpha") == 0)); kdb_bp_template.bp_forcehw = ((strcmp(argv[0], "bph") == 0) || (strcmp(argv[0], "bpha") == 0)); /* Fix me: "bp" is treated as "bpa" to avoid system freeze. -jlan */ if (strcmp(argv[0], "bp") == 0) kdb_bp_template.bp_global = 1; nextarg = 1; diag = kdbgetaddrarg(argc, argv, &nextarg, &kdb_bp_template.bp_addr, &offset, &symname); if (diag) return diag; if (!kdb_bp_template.bp_addr) return KDB_BADINT; /* * Find an empty bp structure, to allocate */ free = KDB_MAXBPT; for(bpno=0,bp=kdb_breakpoints; bpno<KDB_MAXBPT; bpno++,bp++) { if (bp->bp_free) { break; } } if (bpno == KDB_MAXBPT) return KDB_TOOMANYBPT; /* * Handle architecture dependent parsing */ diag = kdba_parsebp(argc, argv, &nextarg, &kdb_bp_template); if (diag) { return diag; } /* * Check for clashing breakpoints. * * Note, in this design we can't have hardware breakpoints * enabled for both read and write on the same address, even * though ia64 allows this. */ for(i=0,bp_check=kdb_breakpoints; i<KDB_MAXBPT; i++,bp_check++) { if (!bp_check->bp_free && bp_check->bp_addr == kdb_bp_template.bp_addr && (bp_check->bp_global || bp_check->bp_cpu == kdb_bp_template.bp_cpu)) { kdb_printf("You already have a breakpoint at " kdb_bfd_vma_fmt0 "\n", kdb_bp_template.bp_addr); return KDB_DUPBPT; } } kdb_bp_template.bp_enabled = 1; /* * Actually allocate the breakpoint found earlier */ *bp = kdb_bp_template; bp->bp_free = 0; if (!bp->bp_global) { bp->bp_cpu = smp_processor_id(); } /* * Allocate a hardware breakpoint. If one is not available, * disable the breakpoint, but leave it in the breakpoint * table. When the breakpoint is re-enabled (via 'be'), we'll * attempt to allocate a hardware register for it. */ if (!bp->bp_template.bph_free) { kdba_alloc_hwbp(bp, &diag); if (diag) { bp->bp_enabled = 0; bp->bp_hardtype = 0; kdba_free_hwbp(bp); return diag; } } kdb_printbp(bp, bpno); return 0; }