dlite.c
来自「一个很有名的硬件模拟器。可以模拟CPU」· C语言 代码 · 共 2,262 行 · 第 1/4 页
C
2,262 行
}/* 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(md_addr_t next_PC, /* address of next inst */ int access, /* mem access of last inst */ md_addr_t addr, /* mem addr of last inst */ counter_t icount, /* instruction count */ counter_t 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 */ myfprintf(stdout, "Stopping at code breakpoint #%d @ 0x%08p...\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 */ myfprintf(stdout, "Stopping at read breakpoint #%d @ 0x%08p...\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 */ myfprintf(stdout, "Stopping at write breakpoint #%d @ 0x%08p...\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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ md_addr_t addr; struct range_range_t range; if (nargs != 1) return "wrong number of arguments"; /* check address */ if (!EVAL_INTEGRAL(args[0].as_value.type)) return "address argument must be an integral type"; /* reset addr */ addr = eval_as_addr(args[0].as_value); /* build the range */ range.start.ptype = pt_addr; range.start.pos = addr; range.end.ptype = pt_addr;#ifdef TARGET_ALPHA /* need some extra space here, as functional have multiple entry points depending on if $GP needs to be loaded or not */ range.end.pos = addr + 9;#else /* !TARGET_ALPHA */ range.end.pos = addr + 1;#endif /* TARGET_ALPHA */ /* 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ int access; md_addr_t addr; struct range_range_t range; if (nargs != 1 && nargs != 2) return "wrong number of arguments"; if (nargs == 1) { /* check address */ if (!EVAL_INTEGRAL(args[0].as_value.type)) return "address argument must be an integral type"; /* reset addr */ addr = eval_as_addr(args[0].as_value); /* break on read or write */ access = ACCESS_READ|ACCESS_WRITE; } else if (nargs == 2) { /* check address */ if (!EVAL_INTEGRAL(args[0].as_value.type)) return "address argument must be an integral type"; /* reset addr */ addr = eval_as_addr(args[0].as_value); /* 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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 regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ int id; if (nargs != 1) return "wrong number of arguments"; /* check bp id */ if (!EVAL_INTEGRAL(args[0].as_value.type)) return "id must be an integral type"; id = eval_as_uint(args[0].as_value); 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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 */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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(md_addr_t regs_PC, /* PC of just completed inst */ md_addr_t next_PC, /* PC of next inst to exec */ counter_t cycle, /* current cycle */ int dbreak, /* last break a data break? */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ md_inst_t inst; char *errstr; if (dbreak) { fprintf(stdout, "\n"); fprintf(stdout, "Instruction (now finished) that caused data break:\n"); myfprintf(stdout, "[%10n] 0x%08p: ", cycle, regs_PC); errstr = f_dlite_mem_obj(mem, /* !is_write */FALSE, regs_PC, (char *)&inst, sizeof(inst)); inst = MD_SWAPI(inst); if (errstr) fprintf(stdout, "<invalid memory>: %s", errstr); else md_print_insn(inst, regs_PC, stdout); fprintf(stdout, "\n"); fprintf(stdout, "\n"); } /* read and disassemble instruction */ myfprintf(stdout, "[%10n] 0x%08p: ", cycle, next_PC); errstr = f_dlite_mem_obj(mem, /* !is_write */FALSE, next_PC, (char *)&inst, sizeof(inst)); inst = MD_SWAPI(inst); if (errstr) fprintf(stdout, "<invalid memory>: %s", errstr); else md_print_insn(inst, next_PC, stdout); fprintf(stdout, "\n");}/* DLite command line prompt */#define DLITE_PROMPT "DLite! > "/* DLite debugger main loop */voiddlite_main(md_addr_t regs_PC, /* addr of last inst to exec */ md_addr_t next_PC, /* addr of next inst to exec */ counter_t cycle, /* current procesor cycle */ struct regs_t *regs, /* registers to access */ struct mem_t *mem) /* memory to access */{ 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, regs, mem); 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, regs, mem); if (err_str) fprintf(stdout, "Dlite: error: %s\n", err_str); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?