?? dbgarchlib.c
字號:
/* forward declaration */LOCAL int dbgInterruptPCW; /* used by dbgIntrInfoSave/Restore */LOCAL int dbgHwRegStatus; /* keep status of hardware regs being used *//********************************************************************************* _dbgArchInit - architecture dependent initialization routine** This routine initialize global function pointers that are architecture * specific.** RETURNS: N/A** NOMANUAL*/void _dbgArchInit (void) { _dbgDsmInstRtn = (FUNCPTR) dsm960Inst; }/******************************************************************************** _dbgTraceDisable - disable trace mode** NOMANUAL*/void _dbgTraceDisable (void) { vxPCWClear (PCW_TRACE_ENABLE_MASK); }/******************************************************************************** _dbgFuncCallCheck - check if opcode is a function call** RETURNS: TRUE if op code at the given addr is a subroutine call.** NOMANUAL*/BOOL _dbgFuncCallCheck ( INSTR * pInst /* pointer to instruction to check */ ) { return (dsmFuncCallCheck (pInst)); }#if (BRK_HW_BP != 0)/****************************************************************************** ** _dbgHwAdrsCheck - verify address is valid** Checks to make sure the given adrs is on a 32-bit boundary, and* that it is accessable.** RETURNS: OK or ERROR if address not on a 32-bit boundary or unaccessible.** NOMANUAL*/STATUS _dbgHwAdrsCheck ( INSTR * adrs, /* address to check */ int access /* access type */ ) { UINT32 val; /* dummy for vxMemProbe */ if ((int) adrs & 0x03) return (ERROR);#if CPU==I960CA switch (access) { case DAB_ACCESS_STORE: if (vxMemProbe ((char *)adrs, O_WRONLY, 4, (char *) &val) != OK) { return (ERROR); } break; case HW_INST_BRK: if (vxMemProbe ((char *)adrs, O_RDONLY, 4, (char *) &val) != OK) { return (ERROR); } break; case DAB_ACCESS_DATA_LOAD_OR_STORE: case DAB_ACCESS_DATA_OR_INSTR_FETCH: case DAB_ACCESS_ANY_ACCESS: if (vxMemProbe ((char *)adrs, O_RDONLY, 4, (char *) &val) != OK || vxMemProbe ((char *)adrs, O_WRONLY, 4, (char *) &val) != OK) { return (ERROR); } break; default: break; }#endif /* CPU==I960CA */ return (OK); }/******************************************************************************** _dbgHwDisplay - display a hardware breakpoint ** NOMANUAL*/void _dbgHwDisplay ( BRKENTRY * bp /* breakpoint table entry */ ) { if ((bp->type & BRK_HW_BP) == 0) return; printf (" (hard-");#if CPU==I960CA switch (bp->pHwBp->hbAccess) { case DAB_ACCESS_STORE: printf ("store only)"); break; case DAB_ACCESS_DATA_LOAD_OR_STORE: printf ("data only)"); break; case DAB_ACCESS_DATA_OR_INSTR_FETCH: printf ("data/instr fetch)"); break; case DAB_ACCESS_ANY_ACCESS: printf ("any access)"); break; case HW_INST_BRK: printf ("instruction)"); break; default: printf ("unknown)"); break; }#endif /* CPU==I960CA */ }/******************************************************************************** _dbgHwBpSet - set a data breakpoint register** Access is the type of access that will generate a breakpoint.* 000 - store only* 001 - data only (load or store)* 010 - data or instruction fetch* 011 - any access* 100 - instruction breakpoint** NOMANUAL*/void _dbgHwBpSet ( INSTR * addr, /* address on which to break */ HWBP * pHwBp /* hardware breakpoint */ ) {#if CPU==I960CA switch (pHwBp->hbRegNum) { case REG_NUM_DAB0: dbgDAB0Set ((char *) addr); dbgDAB0Enable (pHwBp->hbAccess); break; case REG_NUM_DAB1: dbgDAB1Set ((char *) addr); dbgDAB1Enable (pHwBp->hbAccess); break; case REG_NUM_IPB0: (void) dbgIPB0Set ((char *)addr); break; case REG_NUM_IPB1: (void) dbgIPB1Set ((char *)addr); break; default: break; }#endif /* CPU==I960CA */ }/******************************************************************************** _dbgHwBpCheck - check if instruction could have caused a data breakpoint** Check to see if the instruction at the given address caused a* memory reference that matches one of the DAB registers.* Or if the address of the instruction itself caused a break.* This would be true if the access type was for instruction fetch.** RETURNS: TRUE if match, FALSE if no match.** NOMANUAL*/BOOL _dbgHwBpCheck ( INSTR * pInstr, /* ptr to instruction to check */ BRKENTRY * bp, /* pointer to breakpoint entry */ int tid, /* task's id */ volatile BOOL checkFlag /* flag to check if breakpoint hit */ ) {#if CPU==I960CA UINT32 addr1; REG_SET regSet; if ((bp->type & BRK_HW_BP) == 0) return (FALSE); /* check to see if instruction addr caused break */ if (pInstr == bp->addr) return (TRUE); taskRegsGet (tid, ®Set); /* check to see if memory reference caused break */ if (dsmMemInstrCheck(pInstr)) { addr1 = dsmMEMInstrRefAddrGet(pInstr, (UINT32 *)®Set); if (bp->addr == (INSTR *) addr1) return (TRUE); } if ((UINT32)bp->addr == (sysCtrlTable[0]&0xfffffffc)) return (TRUE); if ((UINT32)bp->addr == (sysCtrlTable[1]&0xfffffffc)) return (TRUE);#endif /* CPU==I960CA */ return (FALSE); }/******************************************************************************** _dbgHwBpClear - clear a data breakpoint** Clears a data breakpoint based on given regiser number, but does not* free the resource. This is the mechanism used to clear disable* hardware breakpoints when a task is unbreakable.** NOMANUAL*/void _dbgHwBpClear ( HWBP * pHwBp /* hardware breakpoint */ ) {#if CPU==I960CA switch (pHwBp->hbRegNum) { case REG_NUM_DAB0: dbgDAB0Set ((char *) -1); dbgDAB0Disable (); break; case REG_NUM_DAB1: dbgDAB1Set ((char *) -1); dbgDAB1Disable (); break; case REG_NUM_IPB0: (void) dbgIPB0Disable (); break; case REG_NUM_IPB1: (void) dbgIPB1Disable (); break; }#endif /* CPU==I960CA */ }/******************************************************************************** _dbgArchHwBpFree - free hardware breakpoint data entry** NOMANUAL*/void _dbgArchHwBpFree ( HWBP * pHwBp /* pointer to hardware breakpoint data structure */ ) { dbgHwRegStatus &= ~(1<< pHwBp->hbRegNum); }#endif /* (BRK_HW_BP != 0) *//******************************************************************************** _dbgInfoPCGet - exception frame's PC/IP (program counter/instruction * pointer)** RETURNS: PC/IP** NOMANUAL*/INSTR * _dbgInfoPCGet ( BREAK_ESF * pBrkInfo /* pointer to exception frame */ ) { return ((INSTR *) pBrkInfo->faultIP); }/******************************************************************************** _dbgInstSizeGet - get size of instruction in sizeof(INSTR)'s** RETURNS: The size of the instruction.** NOMANUAL*/int _dbgInstSizeGet ( INSTR * pInst /* pointer to instruction to check */ ) { return (dsmNbytes (pInst) / sizeof (INSTR)); }/******************************************************************************** _dbgIntrInfoRestore - restore the info saved by dbgIntrInfoSave** NOMANUAL*/void _dbgIntrInfoRestore ( BREAK_ESF * pBrkInfo /* pointer to execption frame */ ) { pBrkInfo->procCtrl = dbgInterruptPCW; }/******************************************************************************** _dbgIntrInfoSave - save info when breakpoints are hit at interrupt level.** NOMANUAL*/void _dbgIntrInfoSave ( BREAK_ESF * pBrkInfo /* pointer to breakpoint ESF */ ) { dbgInterruptPCW = pBrkInfo->procCtrl; }/******************************************************************************** _dbgRegsAdjust - adjust stack pointer** Adjust the stack pointer of the given REG_SET to remove the * exception frame, caused by the TRACE FAULT.** NOMANUAL*/void _dbgRegsAdjust ( int tid, /* task's id */ TRACE_ESF * pBrkInfo, /* pointer to exception frame */ int * pRegSet, /* pointer to tasks register set */ volatile BOOL flag /* tells what type of ESF to use */ ) { ansiFix = (int)pBrkInfo->faultIP; /* fix ansi warning */ /* NOP for 80960 because fault record (ESF) is * stuck in just before the stack frame for the * fault handler. */ taskRegsSet (tid, (REG_SET *) pRegSet); }/******************************************************************************** _dbgTaskPCSet - set task's pc** NOMANUAL*/void _dbgTaskPCSet ( int tid, /* task's id */ INSTR * pc, /* pc to set */ INSTR * npc /* npc to set (not supported by 960) */ ) { REG_SET regSet; ansiFix = (int)npc; /* fix ansi warning */ if (taskRegsGet (tid, ®Set) ==OK) { regSet.rip = (UINT32) pc; taskRegsSet (tid, ®Set); } }/******************************************************************************** _dbgTaskPCGet - get task's pc** NOMANUAL*/INSTR * _dbgTaskPCGet ( int tid /* task's id */ ) { REG_SET regSet; taskRegsGet (tid, ®Set); return ((INSTR *) regSet.rip); }/******************************************************************************** _dbgRetAdrsGet - address of the subroutine in which has hit a breakpoint** RETURNS: Address of the next instruction to be executed upon* return of the current subroutine.** INTERNAL* BAL instruction will need to be taken into account here.** NOMANUAL*/INSTR * _dbgRetAdrsGet ( REG_SET * pRegSet /* reg set of broken task */ ) {#define MAX_NAME_LEN 80 UINT32 retVal; UINT32 type = 0x00; UINT32 regNum; INT8 name[MAX_NAME_LEN]; REG_SET * pPrevRegSet = (REG_SET *)pRegSet->pfp; INSTR * pInstr0 = (INSTR *)(pRegSet->rip & 0xfffffffc); INSTR * pInstr1 = pInstr0; /* from this address, find the symbol in the symbol table that * is closest yet lower than the address. If this symbol is a leaf-proc * entry, then get the return address either from gx or g14, * depending on whether or not the mov g14, gx instruction has been * executed. If the symbol is not a leaf_proc entry point, * it is a regular function entry. Get the return address from * the rip of the previous frame. Caveat: if an assembly language * symbol starts with an `_', this could fool this algo. into * thinking it is the start of a function. */ strcpy (name, "\0"); symFindByValue (sysSymTbl, (UINT) pInstr0, (char *) &name, (int *) &pInstr0, (SYM_TYPE *) &type); if (!strncmp (&name[strlen(name) - 3], ".lf", 3)) { /* this is a leaf_proc. first we must check to see if we * are sitting on the mov g14, gx instruction If we are, * return the value in g14, otherwise, disect the instruction * and figure out what register is holding the return value */ if ((*pInstr1 & MOV_G14_MASK) == INST_MOV_G14) retVal = pRegSet->g14; else { regNum = (*pInstr0 & SRC_REG_MASK) >> 0x13; retVal = *(((UINT32 *)pRegSet) + regNum); printf ("regNum: 0x%x, retVal: 0x%x 0x%x \n", regNum, retVal, *pInstr0); } /* we still have to figure out if we got to this point in the leaf-proc * via a 'call' or 'bal' instruction. If we came via a call instruction, * the address 'retVal' will point to the 'ret' instruction at the * end of the function. Otherwise, it will be the address of the * instruction following the 'bal'. If 'retVal' does not point to a * 'ret' instruction, we can just return it. * * NOTE: We could still be fooled if caller's 'bal' or 'balx' is * followed by 'ret.' Perhaps we should also check to see if the * instruction preceding 'ret' is 'bx gx' and or some similar check. */ if (((*(INSTR *)retVal) & 0xff000000) != 0x0a000000) return ((INSTR *)retVal); } /* non-leaf_proc function or 'called' leaf-proc */ return ((INSTR *)(pPrevRegSet->rip & 0xfffffffc)); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -