📄 debug.c
字号:
/* * Copyright (C) 1996-1998 by the Board of Trustees * of Leland Stanford Junior University. * * This file is part of the SimOS distribution. * See LICENSE file for terms of the license. * *//***************************************************************** * debug.c * * Support for running gdb on programs that are executing under * mipsy. Right now this will only work under simos, but it would be * nice to have it work for Solo Mipsy as well. * $Author: bosch $ * $File$ *****************************************************************/#include <sys/signal.h>#include "mipsy.h"#include "cp0.h"#include "fpu.h"#include "cpu_state.h"#include "sim_error.h"#include "memref.h"#include "cpu_interface.h"#include "gdb_interface.h"#include "mips_gdb.h"#ifdef USE_FLASHLITE#include "mipsy_interface.h"#include "flash_interface.h"#endif/* Local Variables */static Reg cached_pc;static uint cached_inst;/* Global Variables */int mipsy_sigusr = 0;int mipsy_break_nexti = MIPSY_NOBREAK;int mipsy_debug_mode = 0;/***************************************************************** * mipsy_getreg *****************************************************************/ResultMipsyGetReg(int cpunum, int regnum, Reg *val){ CPUState* P;#ifdef MIPSY_MXS if (PE[cpunum].inMXS) { CopyFromMXS(PE + cpunum); }#endif P = &PE[cpunum]; if(regnum < 0) { return FAILURE; } if (regnum <= RA_REGNUM) { *val = P->R[regnum]; return SUCCESS; } if ((regnum >= FP0_REGNUM) && (regnum <= FP31_REGNUM)) { *val = IntReg(regnum-FP0_REGNUM); return SUCCESS; } switch (regnum) { case PC_REGNUM: *val = P->PC; break; case CAUSE_REGNUM: *val = P->CP0[C0_CAUSE]; break; case BAD_REGNUM: *val = P->CP0[C0_BADVADDR]; break; case HI_REGNUM: *val = P->HI; break; case LO_REGNUM: *val = P->LO; break; case FCRCS_REGNUM: *val = P->FCR[31]; break; case FCRIR_REGNUM: *val = P->FCR[30]; break; case INX_REGNUM: *val = P->CP0[C0_INX]; break; case RAND_REGNUM: *val = P->CP0[C0_RAND]; break; case TLBLO_REGNUM: *val = P->CP0[C0_TLBLO_0]; break; case CTXT_REGNUM: *val = P->CP0[C0_CTXT]; break; case TLBHI_REGNUM: *val = P->CP0[C0_TLBHI]; break; case SR_REGNUM: *val = P->CP0[C0_SR]; break; case EPC_REGNUM: *val = P->CP0[C0_EPC]; break; case ERROR_EPC_REGNUM: *val = P->CP0[C0_ERROR_EPC]; break; case COUNT_REGNUM: *val = P->CP0[C0_COUNT]; break; case COMPARE_REGNUM: *val = P->CP0[C0_COMPARE]; break; case TLBLO1_REGNUM: *val = P->CP0[C0_TLBLO_1]; break; case PGMASK_REGNUM: *val = P->CP0[C0_PGMASK]; break; case NPC_REGNUM: *val = P->nPC; break; default: return FAILURE; } return SUCCESS;}/***************************************************************** * MipsyPutReg *****************************************************************/Result MipsyPutReg(int cpunum, int regnum, Reg val){ CPUState* P;#ifdef MIPSY_MXS if (PE->inMXS) { CPUWarning("mipsy_putreg doesn't work in MXS mode\n"); }#endif P = &PE[cpunum]; if ((regnum < 0) || (regnum >= GDB_NUM_REGS)) { return FAILURE; } if (regnum <= RA_REGNUM) { P->R[regnum] = val; return SUCCESS; } if ((regnum >= FP0_REGNUM) && (regnum <= FP31_REGNUM)) { IntReg(regnum-FP0_REGNUM) = val; return SUCCESS; } switch (regnum) { case PC_REGNUM: /* * This one is a little tricky. If this is set from a PC * annotation, then everything should work fine. By also setting * the P->PC, I cover the case where this is set from gdb. */ P->PC = val; P->nPC = val; P->branchTarget = 0; P->branchStatus = BranchStatus_none; break; case CAUSE_REGNUM: P->CP0[C0_CAUSE] = val; break; case BAD_REGNUM: P->CP0[C0_BADVADDR] = val; break; case HI_REGNUM: P->HI = val; break; case LO_REGNUM: P->LO = val; break; case FCRCS_REGNUM: P->FCR[31] = val; break; case FCRIR_REGNUM: P->FCR[30] = val; break; case INX_REGNUM: P->CP0[C0_INX] = val; break; case RAND_REGNUM: P->CP0[C0_RAND] = val; break; case TLBLO_REGNUM: P->CP0[C0_TLBLO_0] = val; break; case CTXT_REGNUM: P->CP0[C0_CTXT] = val; break; case TLBHI_REGNUM: P->CP0[C0_TLBHI] = val; break; case SR_REGNUM: P->CP0[C0_SR] = val; break; case EPC_REGNUM: P->CP0[C0_EPC] = val; break; case ERROR_EPC_REGNUM: P->CP0[C0_ERROR_EPC] = val; break; case COUNT_REGNUM: P->CP0[C0_COUNT] = val; break; case COMPARE_REGNUM: P->CP0[C0_COMPARE] = val; break; case TLBLO1_REGNUM: P->CP0[C0_TLBLO_1] = val; break; case PGMASK_REGNUM: P->CP0[C0_PGMASK] = val; break; default: return FAILURE; } return SUCCESS;}/***************************************************************** * MipsyGetMem *****************************************************************/ResultMipsyGetMem(int cpuNum, VA vAddr, uint nbytes, char *buf){ PA pAddr; CPUState *P = &PE[cpuNum];#ifdef MIPSY_MXS if (PE[cpuNum].inMXS) { CopyFromMXS(P); }#endif #ifdef USE_FLASHLITE #ifndef SOLO /* Check for SIMRAMALIAS or SIMPROMALIAS. * These are special-cased. At init time, the contents of those * areas are copied from the backdoor into PP-private memory. * We don't want to access the backdoor copies here, but rather * the copies each node sees. */ if (GetFPROMAndFRAM(cpuNum, vAddr, nbytes, buf)) { return SUCCESS; }#endif#endif if (PAGE_NUMBER(vAddr+nbytes-1) == PAGE_NUMBER(vAddr)) { /* common case: entire range fits on one page */ if (TranslateVirtualNoSideeffect(P, vAddr, &pAddr) != SUCCESS) { return FAILURE; /* for now, give up if not in TLB */ } MemRefDebugReadData(cpuNum, vAddr, pAddr, buf, nbytes); } else { PA pAddr2; int bytes_on_first_page = (1<<12) - PAGE_OFFSET(vAddr); VA vaddr2 = (vAddr) + bytes_on_first_page; ASSERT(nbytes <= (1 << NUM_OFFSET_BITS)); if (TranslateVirtualNoSideeffect(P, vAddr, &pAddr) != SUCCESS) { return FAILURE; } if (TranslateVirtualNoSideeffect(P, vaddr2, &pAddr2) != SUCCESS) { return FAILURE; } MemRefDebugReadData(cpuNum, vAddr, pAddr, buf, bytes_on_first_page); MemRefDebugReadData(cpuNum, vaddr2, pAddr2, buf + bytes_on_first_page, nbytes - bytes_on_first_page); } return SUCCESS;}/***************************************************************** * MipsyPutMem *****************************************************************/ResultMipsyPutMem(int cpuNum, VA vAddr, uint nbytes, char *buf){ PA pAddr; CPUState *P = &PE[cpuNum];#ifdef MIPSY_MXS if (PE[cpuNum].inMXS) { CopyFromMXS(P); }#endif #ifdef USE_FLASHLITE #ifndef SOLO /* Check for SIMRAMALIAS or SIMPROMALIAS. * These are special-cased. At init time, the contents of those * areas are copied from the backdoor into PP-private memory. * We don't want to access the backdoor copies here, but rather * the copies each node sees. */ if (PutFPROMAndFRAM(cpuNum, vAddr, nbytes, buf)) { return SUCCESS; }#endif#endif if (PAGE_NUMBER(vAddr+nbytes-1) == PAGE_NUMBER(vAddr)) { /* common case: entire range fits on one page */ if (TranslateVirtualNoSideeffect(P, vAddr, &pAddr) != SUCCESS) { return FAILURE; /* for now, give up if not in TLB */ } MemRefDebugWriteData(cpuNum, vAddr, pAddr, buf, nbytes); } else { PA pAddr2; int bytes_on_first_page = (1<<12) - PAGE_OFFSET(vAddr); VA vaddr2 = (vAddr) + bytes_on_first_page; ASSERT(nbytes <= (1 << NUM_OFFSET_BITS)); if (TranslateVirtualNoSideeffect(P, vAddr, &pAddr) != SUCCESS) { return FAILURE; } if (TranslateVirtualNoSideeffect(P, vaddr2, &pAddr2) != SUCCESS) { return FAILURE; } MemRefDebugWriteData(cpuNum, nbytes, pAddr, buf, bytes_on_first_page); MemRefDebugWriteData(cpuNum, vaddr2, pAddr2, buf + bytes_on_first_page, nbytes - bytes_on_first_page); } return SUCCESS;}Result MipsyTranslateVirtualNoSE(int cpuNum, VA vAddr, PA *pAddr){ return TranslateVirtualNoSideeffect(&PE[cpuNum], vAddr, pAddr) ;}/***************************************************************** * MipsyDebug * * Main entry point into the debugger from normal execution. * * NOTE: the second argument is_break_instruction is set when * we call in due to a single-step trap (from cpu.c) even though * there is no break instruction at the PC. We need to send * the SIGTRAP to gdb in this case. If we send a SIGUSR2 it * stops single-stepping immediately even though we may not * have yet reached the next line boundary (for 'n' or 's'). * * Return value 0 means nothing has changed, go through normal * instruction completion (pc = npc, npc += 4, annotations, etc). * * Return value 1 means PC has changed or instruction at PC has * been overwritten. If you entered the debugger between instructions * abort anything you have read about the next instruction and restart. * If you entered the debugger from a breakpoint, reexecute the * instruction at that PC. * *****************************************************************/int MipsyDebug(int cpunum, int is_break_instruction){ Simdebug_result res; Inst new_inst=0; cached_pc = PE[cpunum].PC; if (MipsyGetMem(cpunum, cached_pc, 4, (char *)&cached_inst) != SUCCESS) { CPUWarning("Debug -- Current instruction at PC=0x%x not mapped!\n", cached_pc); cached_inst = 0; /* nop */ } res = Simdebug_run(is_break_instruction ? SIGTRAP : SIGUSR2, cpunum); switch (res) { case SD_CONTINUE: mipsy_break_nexti = MIPSY_NOBREAK; mipsy_debug_mode = 0; break; case SD_NEXTI_ANYCPU: mipsy_break_nexti = MIPSY_BREAKANYCPU; mipsy_debug_mode = 1; break; default: mipsy_break_nexti = res; mipsy_debug_mode = 1; break; } if (PE[cpunum].PC != cached_pc) { return 1; } if (MipsyGetMem(cpunum,cached_pc,4,(char*)&new_inst) != SUCCESS) { CPUWarning("Debug -- Current instruction at PC=0x%x not mapped!\n"); return 1; } if( cached_inst != new_inst ) { return 1; } return 0;}/***************************************************************** * HandleDebugSignal *****************************************************************/void HandleDebugSignal(int cpuid, int sigusr){ mipsy_debug_mode = 1; if (sigusr) { mipsy_sigusr = 1; } else { if (cpuid == -1) { mipsy_break_nexti = MIPSY_BREAKANYCPU; } else { mipsy_break_nexti = cpuid; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -