void db_print_loc_and_inst(db_addr_t loc) { db_printsym(loc, DB_STGY_PROC, db_printf); db_printf(":\t"); (void) db_disasm(loc, FALSE); }
void db_print_inst( db_addr_t loc, task_t task) { (void) db_disasm(loc, TRUE, task); }
void db_print_loc_and_inst( db_addr_t loc, task_t task) { db_task_printsym(loc, DB_STGY_PROC, task); db_printf(":\t"); (void) db_disasm(loc, TRUE, task); }
/* * Disassemble instruction 'insn' nominally at 'loc'. * 'loc' may in fact contain a breakpoint instruction. */ db_addr_t db_disasm_insn(int insn, db_addr_t loc, bool altfmt) { bool bdslot = false; InstFmt i; i.word = insn; switch (i.JType.op) { case OP_SPECIAL: if (i.word == 0) { db_printf("nop"); break; } /* XXX * "addu" is a "move" only in 32-bit mode. What's the correct * answer - never decode addu/daddu as "move"? */ if (i.RType.func == OP_ADDU && i.RType.rt == 0) { db_printf("move\t%s,%s", reg_name[i.RType.rd], reg_name[i.RType.rs]); break; } db_printf("%s", spec_name[i.RType.func]); switch (i.RType.func) { case OP_SLL: case OP_SRL: case OP_SRA: case OP_DSLL: case OP_DSRL: case OP_DSRA: case OP_DSLL32: case OP_DSRL32: case OP_DSRA32: db_printf("\t%s,%s,%d", reg_name[i.RType.rd], reg_name[i.RType.rt], i.RType.shamt); break; case OP_SLLV: case OP_SRLV: case OP_SRAV: case OP_DSLLV: case OP_DSRLV: case OP_DSRAV: db_printf("\t%s,%s,%s", reg_name[i.RType.rd], reg_name[i.RType.rt], reg_name[i.RType.rs]); break; case OP_MFHI: case OP_MFLO: db_printf("\t%s", reg_name[i.RType.rd]); break; case OP_JR: case OP_JALR: db_printf("\t%s", reg_name[i.RType.rs]); bdslot = true; break; case OP_MTLO: case OP_MTHI: db_printf("\t%s", reg_name[i.RType.rs]); break; case OP_MULT: case OP_MULTU: case OP_DMULT: case OP_DMULTU: case OP_DIV: case OP_DIVU: case OP_DDIV: case OP_DDIVU: db_printf("\t%s,%s", reg_name[i.RType.rs], reg_name[i.RType.rt]); break; case OP_SYSCALL: case OP_SYNC: break; case OP_BREAK: db_printf("\t%d", (i.RType.rs << 5) | i.RType.rt); break; default: db_printf("\t%s,%s,%s", reg_name[i.RType.rd], reg_name[i.RType.rs], reg_name[i.RType.rt]); } break; case OP_SPECIAL2: if (i.RType.func == OP_MUL) db_printf("%s\t%s,%s,%s", spec2_name[i.RType.func & 0x3], reg_name[i.RType.rd], reg_name[i.RType.rs], reg_name[i.RType.rt]); else db_printf("%s\t%s,%s", spec2_name[i.RType.func & 0x3], reg_name[i.RType.rs], reg_name[i.RType.rt]); break; case OP_BCOND: db_printf("%s\t%s,", bcond_name[i.IType.rt], reg_name[i.IType.rs]); goto pr_displ; case OP_BLEZ: case OP_BLEZL: case OP_BGTZ: case OP_BGTZL: db_printf("%s\t%s,", op_name[i.IType.op], reg_name[i.IType.rs]); goto pr_displ; case OP_BEQ: case OP_BEQL: if (i.IType.rs == 0 && i.IType.rt == 0) { db_printf("b\t"); goto pr_displ; } /* FALLTHROUGH */ case OP_BNE: case OP_BNEL: db_printf("%s\t%s,%s,", op_name[i.IType.op], reg_name[i.IType.rs], reg_name[i.IType.rt]); pr_displ: print_addr(loc + 4 + ((short)i.IType.imm << 2)); bdslot = true; break; case OP_COP0: switch (i.RType.rs) { case OP_BCx: case OP_BCy: db_printf("bc0%c\t", "ft"[i.RType.rt & COPz_BC_TF_MASK]); goto pr_displ; case OP_MT: db_printf("mtc0\t%s,%s", reg_name[i.RType.rt], c0_reg[i.RType.rd]); break; case OP_DMT: db_printf("dmtc0\t%s,%s", reg_name[i.RType.rt], c0_reg[i.RType.rd]); break; case OP_MF: db_printf("mfc0\t%s,%s", reg_name[i.RType.rt], c0_reg[i.RType.rd]); break; case OP_DMF: db_printf("dmfc0\t%s,%s", reg_name[i.RType.rt], c0_reg[i.RType.rd]); break; default: db_printf("%s", c0_opname[i.FRType.func]); } break; case OP_COP1: switch (i.RType.rs) { case OP_BCx: case OP_BCy: db_printf("bc1%c\t", "ft"[i.RType.rt & COPz_BC_TF_MASK]); goto pr_displ; case OP_MT: db_printf("mtc1\t%s,f%d", reg_name[i.RType.rt], i.RType.rd); break; case OP_MF: db_printf("mfc1\t%s,f%d", reg_name[i.RType.rt], i.RType.rd); break; case OP_CT: db_printf("ctc1\t%s,f%d", reg_name[i.RType.rt], i.RType.rd); break; case OP_CF: db_printf("cfc1\t%s,f%d", reg_name[i.RType.rt], i.RType.rd); break; default: db_printf("%s.%s\tf%d,f%d,f%d", cop1_name[i.FRType.func], fmt_name[i.FRType.fmt], i.FRType.fd, i.FRType.fs, i.FRType.ft); } break; case OP_J: case OP_JAL: db_printf("%s\t", op_name[i.JType.op]); print_addr((loc & 0xF0000000) | (i.JType.target << 2)); bdslot = true; break; case OP_LWC1: case OP_SWC1: db_printf("%s\tf%d,", op_name[i.IType.op], i.IType.rt); goto loadstore; case OP_LB: case OP_LH: case OP_LW: case OP_LD: case OP_LBU: case OP_LHU: case OP_LWU: case OP_SB: case OP_SH: case OP_SW: case OP_SD: db_printf("%s\t%s,", op_name[i.IType.op], reg_name[i.IType.rt]); loadstore: db_printf("%d(%s)", (short)i.IType.imm, reg_name[i.IType.rs]); break; case OP_ORI: case OP_XORI: if (i.IType.rs == 0) { db_printf("li\t%s,0x%x", reg_name[i.IType.rt], i.IType.imm); break; } /* FALLTHROUGH */ case OP_ANDI: db_printf("%s\t%s,%s,0x%x", op_name[i.IType.op], reg_name[i.IType.rt], reg_name[i.IType.rs], i.IType.imm); break; case OP_LUI: db_printf("%s\t%s,0x%x", op_name[i.IType.op], reg_name[i.IType.rt], i.IType.imm); break; case OP_CACHE: db_printf("%s\t0x%x,0x%x(%s)", op_name[i.IType.op], i.IType.rt, i.IType.imm, reg_name[i.IType.rs]); break; case OP_ADDI: case OP_DADDI: case OP_ADDIU: case OP_DADDIU: if (i.IType.rs == 0) { db_printf("li\t%s,%d", reg_name[i.IType.rt], (short)i.IType.imm); break; } /* FALLTHROUGH */ default: db_printf("%s\t%s,%s,%d", op_name[i.IType.op], reg_name[i.IType.rt], reg_name[i.IType.rs], (short)i.IType.imm); } db_printf("\n"); if (bdslot) { db_printf("\t\tbdslot:\t"); db_disasm(loc+4, false); return (loc + 8); } return (loc + 4); }
void db_examine(db_addr_t addr, char *fmt, int count) { int c; db_expr_t value; int size; int width; char * fp; char tmpfmt[28]; while (--count >= 0) { fp = fmt; size = 4; width = 12; while ((c = *fp++) != 0) { if (db_print_position() == 0) { /* Always print the address. */ db_printsym(addr, DB_STGY_ANY, db_printf); db_printf(":\t"); db_prev = addr; } switch (c) { case 'b': /* byte */ size = 1; width = 4; break; case 'h': /* half-word */ size = 2; width = 8; break; case 'l': /* long-word */ size = 4; width = 12; break; #ifdef __LP64__ case 'q': /* quad-word */ size = 8; width = 20; break; #endif case 'a': /* address */ db_printf("= 0x%lx\n", (long)addr); break; case 'r': /* signed, current radix */ value = db_get_value(addr, size, TRUE); addr += size; db_format(tmpfmt, sizeof tmpfmt, (long)value, DB_FORMAT_R, 0, width); db_printf("%-*s", width, tmpfmt); break; case 'x': /* unsigned hex */ value = db_get_value(addr, size, FALSE); addr += size; db_printf("%-*lx", width, (long)value); break; case 'z': /* signed hex */ value = db_get_value(addr, size, TRUE); addr += size; db_format(tmpfmt, sizeof tmpfmt, (long)value, DB_FORMAT_Z, 0, width); db_printf("%-*s", width, tmpfmt); break; case 'd': /* signed decimal */ value = db_get_value(addr, size, TRUE); addr += size; db_printf("%-*ld", width, (long)value); break; case 'u': /* unsigned decimal */ value = db_get_value(addr, size, FALSE); addr += size; db_printf("%-*lu", width, (long)value); break; case 'o': /* unsigned octal */ value = db_get_value(addr, size, FALSE); addr += size; db_printf("%-*lo", width, value); break; case 'c': /* character */ value = db_get_value(addr, 1, FALSE); addr += 1; if (value >= ' ' && value <= '~') db_printf("%c", value); else db_printf("\\%03o", value); break; case 's': /* null-terminated string */ for (;;) { value = db_get_value(addr, 1, FALSE); addr += 1; if (value == 0) break; if (value >= ' ' && value <= '~') db_printf("%c", value); else db_printf("\\%03o", value); } break; case 'i': /* instruction */ addr = db_disasm(addr, FALSE); break; case 'I': /* instruction, alternate form */ addr = db_disasm(addr, TRUE); break; default: break; } if (db_print_position() != 0) db_end_line(width); } } db_next = addr; }
static void db_examine(db_addr_t addr, char *fmt, int count) { int i, c; db_expr_t value; int size; int width; int bytes; char * fp; char tbuf[24]; while (--count >= 0) { fp = fmt; size = 4; width = 12; while ((c = *fp++) != 0) { if (db_print_position() == 0) { /* Always print the address. */ db_printsym(addr, DB_STGY_ANY, db_printf); db_printf(":\t"); db_prev = addr; } switch (c) { case 'b': /* byte */ size = 1; width = 4; break; case 'h': /* half-word */ size = 2; width = 8; break; case 'l': /* long-word */ size = 4; width = 12; break; case 'q': if (sizeof(db_expr_t) != sizeof(uint64_t)) { size = -1; db_error("q not supported\n"); /*NOTREACHED*/ } case 'L': /* implementation maximum */ size = sizeof value; width = 12 * (sizeof value / 4); break; case 'a': /* address */ db_printf("= 0x%lx\n", (long)addr); break; case 'r': /* signed, current radix */ value = db_get_value(addr, size, true); addr += size; db_format_radix(tbuf, 24, value, false); db_printf("%-*s", width, tbuf); break; case 'x': /* unsigned hex */ value = db_get_value(addr, size, false); addr += size; db_printf("%-*" DDB_EXPR_FMT "x", width, value); break; case 'm': /* hex dump */ /* * Print off in chunks of size. Try to print 16 * bytes at a time into 4 columns. This * loops modify's count extra times in order * to get the nicely formatted lines. */ bytes = 0; do { for (i = 0; i < size; i++) { value = db_get_value(addr+bytes, 1, false); db_printf( "%02" DDB_EXPR_FMT "x", value); bytes++; if (!(bytes % 4)) db_printf(" "); } } while ((bytes != 16) && count--); /* True up the columns before continuing */ for (i = 4; i >= (bytes / 4); i--) db_printf ("\t"); /* Print chars, use . for non-printable's. */ while (bytes--) { value = db_get_value(addr, 1, false); addr += 1; if (value >= ' ' && value <= '~') db_printf("%c", (char)value); else db_printf("."); } db_printf("\n"); break; case 'z': /* signed hex */ value = db_get_value(addr, size, true); addr += size; db_format_hex(tbuf, 24, value, false); db_printf("%-*s", width, tbuf); break; case 'd': /* signed decimal */ value = db_get_value(addr, size, true); addr += size; db_printf("%-*" DDB_EXPR_FMT "d", width, value); break; case 'u': /* unsigned decimal */ value = db_get_value(addr, size, false); addr += size; db_printf("%-*" DDB_EXPR_FMT "u", width, value); break; case 'o': /* unsigned octal */ value = db_get_value(addr, size, false); addr += size; db_printf("%-*" DDB_EXPR_FMT "o", width, value); break; case 'c': /* character */ value = db_get_value(addr, 1, false); addr += 1; if (value >= ' ' && value <= '~') db_printf("%c", (char)value); else db_printf("\\%03o", (int)value); break; case 's': /* null-terminated string */ for (;;) { value = db_get_value(addr, 1, false); addr += 1; if (value == 0) break; if (value >= ' ' && value <= '~') db_printf("%c", (char)value); else db_printf("\\%03o", (int)value); } break; case 'i': /* instruction */ addr = db_disasm(addr, false); break; case 'I': /* instruction, alternate form */ addr = db_disasm(addr, true); break; default: break; } if (db_print_position() != 0) db_end_line(); } } db_next = addr; }
void db_examine( db_addr_t addr, char * fmt, /* format string */ int count, /* repeat count */ task_t task) { int c; db_expr_t value; int size; int width; int leader; int items; int nitems; char * fp; db_addr_t next_addr; int sz; db_examine_prev_addr = addr; while (--count >= 0) { fp = fmt; size = sizeof(int); width = db_examine_width(size, &items, &leader); while ((c = *fp++) != 0) { switch (c) { case 'b': size = sizeof(char); width = db_examine_width(size, &items, &leader); break; case 'h': size = sizeof(short); width = db_examine_width(size, &items, &leader); break; case 'l': size = sizeof(int); width = db_examine_width(size, &items, &leader); break; case 'q': size = sizeof(long); width = db_examine_width(size, &items, &leader); break; case 'a': /* address */ case 'A': /* function address */ /* always forces a new line */ if (db_print_position() != 0) db_printf("\n"); db_prev = addr; next_addr = addr + 4; db_task_printsym(addr, (c == 'a')?DB_STGY_ANY:DB_STGY_PROC, task); db_printf(":\t"); break; case 'm': db_next = db_xcdump(addr, size, count+1, task); return; case 't': case 'u': break; default: restart: /* Reset next_addr in case we are printing in multiple formats. */ next_addr = addr; if (db_print_position() == 0) { /* If we hit a new symbol, print it */ char * name; db_addr_t off; db_find_task_sym_and_offset(addr,&name,&off,task); if (off == 0) db_printf("\r%s:\n", name); db_printf("%#n: ", addr); for (sz = 0; sz < leader; sz++) db_putchar(' '); db_prev = addr; nitems = items; } switch (c) { case 'p': /* Addrs rendered symbolically. */ if( size == sizeof(void *) ) { char *symName; db_addr_t offset; items = 1; value = db_get_task_value( next_addr, sizeof(db_expr_t), FALSE, task ); db_find_task_sym_and_offset( value, &symName, &offset, task); db_printf("\n\t*%8x(%8X) = %s", next_addr, value, symName ); if( offset ) { db_printf("+%X", offset ); } next_addr += size; } break; case 'r': /* signed, current radix */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), TRUE,task); db_printf("%-*r", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, TRUE, task); db_printf("%-*R", width, value); next_addr += sz; } break; case 'x': /* unsigned hex */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), FALSE,task); db_printf("%-*x", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, FALSE, task); db_printf("%-*X", width, value); next_addr += sz; } break; case 'z': /* signed hex */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), TRUE, task); db_printf("%-*z", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr,sz, TRUE,task); db_printf("%-*Z", width, value); next_addr += sz; } break; case 'd': /* signed decimal */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), TRUE,task); db_printf("%-*d", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, TRUE, task); db_printf("%-*D", width, value); next_addr += sz; } break; case 'U': /* unsigned decimal */ case 'u': for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), FALSE,task); db_printf("%-*u", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, FALSE, task); db_printf("%-*U", width, value); next_addr += sz; } break; case 'o': /* unsigned octal */ for (sz = size, next_addr = addr; sz >= sizeof (db_expr_t); sz -= sizeof (db_expr_t)) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sizeof (db_expr_t), FALSE,task); db_printf("%-*o", width, value); next_addr += sizeof (db_expr_t); } if (sz > 0) { if (nitems-- == 0) { db_putchar('\n'); goto restart; } value = db_get_task_value(next_addr, sz, FALSE, task); db_printf("%-*o", width, value); next_addr += sz; } break; case 'c': /* character */ for (sz = 0, next_addr = addr; sz < size; sz++, next_addr++) { value = db_get_task_value(next_addr,1, FALSE,task); if ((value >= ' ' && value <= '~') || value == '\n' || value == '\t') db_printf("%c", value); else db_printf("\\%03o", value); } break; case 's': /* null-terminated string */ size = 0; for (;;) { value = db_get_task_value(next_addr,1, FALSE,task); next_addr += 1; size++; if (value == 0) break; if (value >= ' ' && value <= '~') db_printf("%c", value); else db_printf("\\%03o", value); } break; case 'i': /* instruction */ next_addr = db_disasm(addr, FALSE, task); size = next_addr - addr; break; case 'I': /* instruction, alternate form */ next_addr = db_disasm(addr, TRUE, task); size = next_addr - addr; break; default: break; } if (db_print_position() != 0) db_end_line(); break; } } addr = next_addr; } db_next = addr; }