📄 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. * */#include <bstring.h>#include <sys/signal.h>#include "gdb_interface.h"#include "mips_gdb.h"#include "simmisc.h"#include "embra.h"#include "debug.h"#include "clock.h"#include "main_run.h"#include "qc.h"#include "driver.h"#include "mem_control.h"#include "tcl_init.h"#include "tc.h"#include "cp0.h"#include "machine_params.h"/* Known Bugs: If you enter debugger when processes are in promslave loop *//* then you won't restart after. */#define DEBUG 1#define BREAKPOINT 0x1#define SINGLESTEP 0x2#define SIGNAL 0x4#define INCR_PC 0x8#define FLUSH_TC 0x10#define SIDE_EFFECT 0x20#define SIGNAL_USR 0x2static struct EmbraDebug { uint statusCode; int ignoreNextOne; int processingAnn; int processingGDB; SimTime lastDebugCycle[SIM_MAXCPUS];} embraDebug;/* ******************************************************** * EmbraSideEffect is called whenever a change in the machine * state (registers, not memory) occured during a callout. * ********************************************************/void EmbraDebugInit(void){ int i; embraDebug.statusCode = 0; embraDebug.processingAnn = 0; embraDebug.processingGDB = 0; for (i=0;i<TOTAL_CPUS;i++) { embraDebug.lastDebugCycle[i] = 0; }}void EmbraSideEffect(void) { if (embraDebug.processingAnn) { embraDebug.statusCode |= SIDE_EFFECT; }}void EmbraDebug( int cpuNum ){ int incrpc = embraDebug.statusCode & INCR_PC; ASSERT( embra.sequential); Simdebug_run(((embraDebug.statusCode & BREAKPOINT) ? SIGTRAP : SIGUSR2 ), cpuNum); if (embraDebug.processingAnn ) { /* * finish the annotation first, then * check for side-effects,... */ return; } if (embraDebug.processingGDB) { FlushTCIfNecessary(cpuNum); if( incrpc ) { EMP[cpuNum].PC += INST_SIZE; } ASSERT( (EMP[cpuNum].PC & 0x3) == 0 ); embraDebug.statusCode &= ~SIDE_EFFECT; embraDebug.processingGDB = 0; ReenterTC( &EMP[cpuNum] ); /* NOT REACHED */ return; } }void FlushTCIfNecessary(int cpuNum){ if( embraDebug.statusCode & FLUSH_TC ) { /* *this bit might get set in Simdebug_run */ /* The following call does not work for * MPinMP. However, MPinUP ignores the * cpuNum argument so it is fine. * * Problem is that debugger could have modified * stuff that is in any cpu, so we need to * flush stuff across the board. */ Clear_Translation_State( TCFLUSH_ALL); embraDebug.statusCode &=~FLUSH_TC; }}int EmbraAnnType(void){ return embraDebug.processingAnn;}/* ************************************************************** * Embra_Handle_Debug_Signal * * Called through CPUVec in the case of a debug annotation * and in the case of a SIGUSR1 * **************************************************************/void Embra_Handle_Debug_Signal( int cpuid, int sigusr ){ /* * Handle the debugging or the signal synchronously * However, we need to make sure that time has advanced, * else, we will go into an infinite loop. * Annotations that are on the same pc/mem location will * be executed twice, with the exception of the debugging * interaction (that ocurs once). * * This is required since we need to do a ReenterTC after * the debugging interaction. */ /* Check this value when we drop into debugger, it allows us to set the embraDebug.statusCode */ int cpu = (cpuid<0?CPUVec.CurrentCpuNum():cpuid); ASSERT( cpu >= 0 && cpu < TOTAL_CPUS); if (sigusr) { embraDebug.statusCode = SIGNAL_USR; } else { /* * process the debugging requests immediately */ EmbraDebug(cpu); }}/* This gets called from a kernel breakpoint */void Embra_SimosKernDebugBreak( int cpuNum ){ ASSERT (curEmp->myNum == cpuNum); CPUWarning("DEBUGGER at %#x\n",EMP[cpuNum].PC); embraDebug.statusCode = 0; embraDebug.statusCode |= BREAKPOINT; embraDebug.statusCode |= INCR_PC; /* Kernel breakpoints are stepped over */ embraDebug.processingGDB = 1; EmbraDebug(cpuNum);}/* * this gets from a breakpoint too. Used to step. */void Embra_SimosDebugBreak( int cpuNum ){ ASSERT (curEmp->myNum == cpuNum); CPUWarning("DEBUG: Debug break\n"); if( embraDebug.lastDebugCycle[cpuNum]== EmbraCpuCycleCount( cpuNum ) ) { /* prevent infinite loop * This is our way of stepping over the code that calls the annotation * by disabling it the next time around. * Catch: any other annotations installed at the same PC * will be called twice. */ CPUWarning("Embra_SimosDebugBreak: skip \n"); return; } embraDebug.lastDebugCycle[cpuNum] = EmbraCpuCycleCount( cpuNum ); embraDebug.statusCode = 0; embraDebug.statusCode |= BREAKPOINT; embraDebug.processingGDB = 1; EmbraDebug(cpuNum);}/* No one returns from this procedure *//* We leave via the execption path *//* This insures that if we wrote registers, our register allocaiton in *//* translation won't break *//* ***************************************************************** * EmbraPollSigUsr. * the last thing we want to do is to interpret Tcl scripts on the * signal stack. Called from the periodic callout * *****************************************************************/void EmbraPollSigUsr( int cpuNum ){ if (embraDebug.statusCode & SIGNAL_USR) { embraDebug.statusCode &= ~SIGNAL_USR; AnnExec(AnnFind("simos", "sigusr")); }}/* ************************************************************** * EmbraAnnExec * * returns unless the annotation has a side-effect on the machine * state. * * XXX Known limitiation: if the tcl script has side-effects and * the PC is in a delay slot, we are hosed!!! (for now) * * **************************************************************/void EmbraAnnExec(int cpuNum,AnnPtr ptr, int annType){ VA pc = EMP[cpuNum].PC; ASSERT (!embraDebug.processingAnn); ASSERT (annType); if (embraDebug.ignoreNextOne) { embraDebug.ignoreNextOne = 0; if (DEBUG) { CPUWarning("EmbraAnnExec: skipping annotation \n"); } return; } embraDebug.statusCode &= ~(SIDE_EFFECT|FLUSH_TC); embraDebug.processingAnn = annType; AnnExec(ptr); embraDebug.processingAnn = 0; if (embraDebug.statusCode & FLUSH_TC) { ASSERT (embraDebug.statusCode & SIDE_EFFECT); Clear_Translation_State( TCFLUSH_ALL); } if (embraDebug.statusCode & SIDE_EFFECT) { if (annType==ANNFM_LD_TYPE || annType==ANNFM_ST_TYPE || annType==ANNFM_PRE_PC_TYPE) { if (EMP[cpuNum].PC == pc) { embraDebug.ignoreNextOne = 1; } } else { ASSERT (annType==ANNFM_PC_TYPE); if (EMP[cpuNum].PC ==pc) { /* * there we better skip the instruction * as some are not idempotent. */ ASSERT( !IN_BD(EMP[cpuNum].PC)); EMP[cpuNum].PC += INST_SIZE; EMP[cpuNum].cycleCountdown--; } } ASSERT( !IN_BD(EMP[cpuNum].PC)); ReenterTC(&EMP[cpuNum]); /* NOTREACHED */ } embraDebug.statusCode &= ~FLUSH_TC; embraDebug.statusCode &= ~SIDE_EFFECT;} /* ************************************************************** * Callbacks during the gdb session. These have side-effects on
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -