📄 dlite.c
字号:
ss_print_insn(inst, addr, stdout); fprintf(stdout, "\n"); /* go to next instruction */ addr += SS_INST_SIZE; } /* no error */ return NULL;}/* break instance descriptor, one allocated for each breakpoint set */struct dlite_break_t { struct dlite_break_t *next; /* next active breakpoint */ int id; /* break id */ int class; /* break class */ struct range_range_t range; /* break range */};/* all active break points, in a list */static struct dlite_break_t *dlite_bps = NULL;/* unique id of next breakpoint */static int break_id = 1;/* return breakpoint class as a string */static char * /* breakpoint class string */bp_class_str(int class) /* breakpoint class mask */{ if (class == (ACCESS_READ|ACCESS_WRITE|ACCESS_EXEC)) return "read|write|exec"; else if (class == (ACCESS_READ|ACCESS_WRITE)) return "read|write"; else if (class == (ACCESS_WRITE|ACCESS_EXEC)) return "write|exec"; else if (class == (ACCESS_READ|ACCESS_EXEC)) return "read|exec"; else if (class == ACCESS_READ) return "read"; else if (class == ACCESS_WRITE) return "write"; else if (class == ACCESS_EXEC) return "exec"; else panic("bogus access class");}/* set a breakpoint of class CLASS at address ADDR */static char * /* err str, NULL for no err */set_break(int class, /* break class, use ACCESS_* */ struct range_range_t *range) /* range breakpoint */{ struct dlite_break_t *bp; /* add breakpoint to break list */ bp = calloc(1, sizeof(struct dlite_break_t)); if (!bp) fatal("out of virtual memory"); bp->id = break_id++; bp->range = *range; bp->class = class; bp->next = dlite_bps; dlite_bps = bp; fprintf(stdout, "breakpoint #%d set @ ", bp->id); range_print_range(&bp->range, stdout); fprintf(stdout, ", class: %s\n", bp_class_str(class)); /* a breakpoint is set now, check for a breakpoint */ dlite_check = TRUE; /* no error */ return NULL;}/* delete breakpoint with id ID */static char * /* err str, NULL for no err */delete_break(int id) /* id of brkpnt to delete */{ struct dlite_break_t *bp, *prev; if (!dlite_bps) return "no breakpoints set"; for (bp=dlite_bps,prev=NULL; bp != NULL; prev=bp,bp=bp->next) { if (bp->id == id) break; } if (!bp) return "breakpoint not found"; if (!prev) { /* head of list, unlink */ dlite_bps = bp->next; } else { /* middle or end of list */ prev->next = bp->next; } fprintf(stdout, "breakpoint #%d deleted @ ", bp->id); range_print_range(&bp->range, stdout); fprintf(stdout, ", class: %s\n", bp_class_str(bp->class)); bp->next = NULL; free(bp); if (!dlite_bps) { /* no breakpoints set, cancel checks */ dlite_check = FALSE; } else { /* breakpoints are set, do checks */ dlite_check = TRUE; } /* no error */ return NULL;}/* this variable clues dlite_main() into why it was called */static int break_access = 0;/* internal break check interface */int /* non-zero if brkpt hit */__check_break(SS_ADDR_TYPE next_PC, /* address of next inst */ int access, /* mem access of last inst */ SS_ADDR_TYPE addr, /* mem addr of last inst */ SS_COUNTER_TYPE icount, /* instruction count */ SS_COUNTER_TYPE cycle) /* cycle count */{ struct dlite_break_t *bp; if (dlite_active) { /* single-stepping, break always */ break_access = /* single step */0; return TRUE; } /* else, check for a breakpoint */ for (bp=dlite_bps; bp != NULL; bp=bp->next) { switch (bp->range.start.ptype) { case pt_addr: if ((bp->class & ACCESS_EXEC) && !range_cmp_range(&bp->range, next_PC)) { /* hit a code breakpoint */ fprintf(stdout, "Stopping at code breakpoint #%d @ 0x%08x...\n", bp->id, next_PC); break_access = ACCESS_EXEC; return TRUE; } if ((bp->class & ACCESS_READ) && ((access & ACCESS_READ) && !range_cmp_range(&bp->range, addr))) { /* hit a read breakpoint */ fprintf(stdout, "Stopping at read breakpoint #%d @ 0x%08x...\n", bp->id, addr); break_access = ACCESS_READ; return TRUE; } if ((bp->class & ACCESS_WRITE) && ((access & ACCESS_WRITE) && !range_cmp_range(&bp->range, addr))) { /* hit a write breakpoint */ fprintf(stdout, "Stopping at write breakpoint #%d @ 0x%08x...\n", bp->id, addr); break_access = ACCESS_WRITE; return TRUE; } break; case pt_inst: if (!range_cmp_range(&bp->range, icount)) { /* hit a code breakpoint */ fprintf(stdout, "Stopping at inst count breakpoint #%d @ %.0f...\n", bp->id, (double)icount); break_access = ACCESS_EXEC; return TRUE; } break; case pt_cycle: if (!range_cmp_range(&bp->range, cycle)) { /* hit a code breakpoint */ fprintf(stdout, "Stopping at cycle count breakpoint #%d @ %.0f...\n", bp->id, (double)cycle); break_access = ACCESS_EXEC; return TRUE; } break; default: panic("bogus range type"); } } /* no matching breakpoint found */ break_access = /* no break */0; return FALSE;}/* set a text breakpoint */static char * /* err str, NULL for no err */dlite_break(int nargs, union arg_val_t args[]) /* command arguments */{ SS_ADDR_TYPE addr; struct range_range_t range; if (nargs != 1) return "wrong number of arguments"; /* check address */ if (args[0].as_value.type != et_int && args[0].as_value.type != et_uint) return "address argument must be an integral type"; /* reset addr */ addr = args[0].as_value.value.as_uint; /* build the range */ range.start.ptype = pt_addr; range.start.pos = addr; range.end.ptype = pt_addr; range.end.pos = addr + 1; /* set a code break point */ return set_break(ACCESS_EXEC, &range);}/* set a data breakpoint at specified address */static char * /* err str, NULL for no err */dlite_dbreak(int nargs, union arg_val_t args[]) /* command arguments */{ int access; SS_ADDR_TYPE addr; struct range_range_t range; if (nargs != 1 && nargs != 2) return "wrong number of arguments"; if (nargs == 1) { /* check address */ if (args[0].as_value.type != et_int && args[0].as_value.type != et_uint) return "address argument must be an integral type"; /* reset addr */ addr = args[0].as_value.value.as_uint; /* break on read or write */ access = ACCESS_READ|ACCESS_WRITE; } else if (nargs == 2) { /* check address */ if (args[0].as_value.type != et_int && args[0].as_value.type != et_uint) return "address argument must be an integral type"; /* reset addr */ addr = args[0].as_value.value.as_uint; /* get access */ access = args[1].as_access; } /* build the range */ range.start.ptype = pt_addr; range.start.pos = addr; range.end.ptype = pt_addr; range.end.pos = addr + 1; /* set the breakpoint */ return set_break(access, &range);}/* set a breakpoint at specified range */static char * /* err str, NULL for no err */dlite_rbreak(int nargs, union arg_val_t args[]) /* command arguments */{ int access; char *errstr; struct range_range_t range; if (nargs != 1 && nargs != 2) return "wrong number of arguments"; if (nargs == 2) { /* get access */ access = args[1].as_access; } else { /* break on read or write or exec */ access = ACCESS_READ|ACCESS_WRITE|ACCESS_EXEC; } /* check range */ errstr = range_parse_range(args[0].as_str, &range); if (errstr) return errstr; /* sanity checks for ranges */ if (range.start.ptype != range.end.ptype) return "range endpoints are not of the same type"; else if (range.start.pos > range.end.pos) return "range start is after range end"; /* set the breakpoint */ return set_break(access, &range);}/* list all outstanding breakpoints */static char * /* err str, NULL for no err */dlite_breaks(int nargs, union arg_val_t args[]) /* command arguments */{ struct dlite_break_t *bp; if (!dlite_bps) { fprintf(stdout, "No active breakpoints.\n"); /* no error */ return NULL; } fprintf(stdout, "Active breakpoints:\n"); for (bp=dlite_bps; bp != NULL; bp=bp->next) { fprintf(stdout, " breakpoint #%d @ ", bp->id); range_print_range(&bp->range, stdout); fprintf(stdout, ", class: %s\n", bp_class_str(bp->class)); } /* no error */ return NULL;}/* delete specified breakpoint */static char * /* err str, NULL for no err */dlite_delete(int nargs, union arg_val_t args[]) /* command arguments */{ int id; if (nargs != 1) return "wrong number of arguments"; /* check bp id */ if (args[0].as_value.type != et_int && args[0].as_value.type != et_uint) return "id must be an integral type"; id = args[0].as_value.value.as_uint; return delete_break(id);}/* clear all breakpoints */static char * /* err str, NULL for no err */dlite_clear(int nargs, union arg_val_t args[]) /* command arguments */{ if (!dlite_bps) { fprintf(stdout, "No active breakpoints.\n"); /* no error */ return NULL; } while (dlite_bps != NULL) { /* delete first breakpoint */ delete_break(dlite_bps->id); } fprintf(stdout, "All breakpoints cleared.\n"); /* no error */ return NULL;}/* print the value of all program symbols */static char * /* err str, NULL for no err */dlite_symbols(int nargs, union arg_val_t args[])/* command arguments */{ int i; if (nargs != 0) return "wrong number of arguments"; /* load symbols, if not already loaded */ sym_loadsyms(ld_prog_fname, /* !locals */FALSE); /* print all symbol values */ for (i=0; i<sym_nsyms; i++) sym_dumpsym(sym_syms[i], stdout); /* no error */ return NULL;}/* print the value of all text symbols */static char * /* err str, NULL for no err */dlite_tsymbols(int nargs, union arg_val_t args[])/* command arguments */{ int i; if (nargs != 0) return "wrong number of arguments"; /* load symbols, if not already loaded */ sym_loadsyms(ld_prog_fname, /* !locals */FALSE); /* print all symbol values */ for (i=0; i<sym_ntextsyms; i++) sym_dumpsym(sym_textsyms[i], stdout); /* no error */ return NULL;}/* print the value of all text symbols */static char * /* err str, NULL for no err */dlite_dsymbols(int nargs, union arg_val_t args[])/* command arguments */{ int i; if (nargs != 0) return "wrong number of arguments"; /* load symbols, if not already loaded */ sym_loadsyms(ld_prog_fname, /* !locals */FALSE); /* print all symbol values */ for (i=0; i<sym_ndatasyms; i++) sym_dumpsym(sym_datasyms[i], stdout); /* no error */ return NULL;}/* print the value of all (or single) command line options */static char * /* err str, NULL for no err */dlite_symbol(int nargs, union arg_val_t args[]) /* command arguments */{ int index; struct sym_sym_t *sym; if (nargs != 1) return "wrong number of arguments"; /* load symbols, if not already loaded */ sym_loadsyms(ld_prog_fname, /* !locals */FALSE); /* print a single option, specified by argument */ sym = sym_bind_name(args[0].as_str, &index, sdb_any); if (!sym) return "symbol is not defined"; /* else, print this symbols's value */ sym_dumpsym(sym_syms_by_name[index], stdout); /* no error */ return NULL;}/* initialize the DLite debugger */voiddlite_init(dlite_reg_obj_t reg_obj, /* register state object */ dlite_mem_obj_t mem_obj, /* memory state object */ dlite_mstate_obj_t mstate_obj) /* machine state object */{ /* architected state accessors */ f_dlite_reg_obj = reg_obj; f_dlite_mem_obj = mem_obj; f_dlite_mstate_obj = mstate_obj; /* instantiate the expression evaluator */ dlite_evaluator = eval_new(ident_evaluator, NULL);}/* print a mini-state header */static voiddlite_status(SS_ADDR_TYPE regs_PC, /* PC of just completed inst */ SS_ADDR_TYPE next_PC, /* PC of next inst to exec */ SS_COUNTER_TYPE cycle, /* current cycle */ int dbreak) /* last break a data break? */{ SS_INST_TYPE inst; char *errstr; if (dbreak) { fprintf(stdout, "\n"); fprintf(stdout, "Instruction (now finished) that caused data break:\n"); fprintf(stdout, "[%10.0f] 0x%08x: ", (double)cycle, regs_PC); errstr = f_dlite_mem_obj(at_read, regs_PC, (char *)&inst, sizeof(inst)); if (errstr) fprintf(stdout, "<invalid memory>"); else ss_print_insn(inst, regs_PC, stdout); fprintf(stdout, "\n"); fprintf(stdout, "\n"); } /* read and disassemble instruction */ fprintf(stdout, "[%10.0f] 0x%08x: ", (double)cycle, next_PC); errstr = f_dlite_mem_obj(at_read, next_PC, (char *)&inst, sizeof(inst)); if (errstr) fprintf(stdout, "<invalid memory>"); else ss_print_insn(inst, next_PC, stdout); fprintf(stdout, "\n");}/* DLite command line prompt */#define DLITE_PROMPT "DLite! > "/* DLite debugger main loop */voiddlite_main(SS_ADDR_TYPE regs_PC, /* addr of last inst to exec */ SS_ADDR_TYPE next_PC, /* addr of next inst to exec */ SS_COUNTER_TYPE cycle) /* current cycle */{ char buf[512], *err_str; int dbreak = (break_access & (ACCESS_READ|ACCESS_WRITE)) != 0; static char cmd[512] = ""; dlite_active = TRUE; dlite_return = FALSE; dlite_status(regs_PC, next_PC, cycle, dbreak); while (dlite_active && !dlite_return) { fprintf(stdout, DLITE_PROMPT); fflush(stdout); fgets(buf, 512, stdin); /* chop */ if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; if (buf[0] != '\0') { /* use this command */ strcpy(cmd, buf); } /* else, use last command */ err_str = dlite_exec(cmd); if (err_str) fprintf(stdout, "Dlite: error: %s\n", err_str); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -