📄 trclib.c
字号:
( INSTR * callAdrs, /* address from which function was called */ INSTR * funcAdrs, /* address of function called */ FAST int nargs, /* number of arguments in function call */ int * args /* pointer to function args */ ) { FAST int ix; BOOL doingDefault = FALSE; /* print call address and function address */ printErr ("%6x: %x (", callAdrs, funcAdrs); /* if no args are specified, print out default number (see doc at top) */ if ((nargs == 0) && (trcDefaultArgs != 0)) { doingDefault = TRUE; nargs = trcDefaultArgs; printErr ("["); } /* print args */ for (ix = 0; ix < nargs; ++ix) { if (ix != 0) printErr (", ");#if (CPU == MIPS64) printErr ("%x", args[ix * 2]);#else /* (CPU == MIPS64) */ printErr ("%x", args[ix]);#endif /* (CPU == MIPS64) */ } if (doingDefault) printErr ("]"); printErr (")\n"); }/****************************************************************************** trcFindFuncStart - find the starting address of a function** This routine finds the starting address of a function.* For MIPS processors, to find the start of a function, we use the instruction* where the function was called from to compute it. The call was one of * a "jal", "jalr" or "BxAL[L]" instruction. For "jalr", it will be impossible* to determine the target address since the contents of the target register* have been lost along the way.*/LOCAL INSTR *trcFindFuncStart ( REG_SET * regs, /* general purpose registers */ INSTR * callpc /* pc of the calling point */ ) {#ifdef DBG_PRINTF (void)printf("trcFindFuncStart entry.\n");#endif /* DBG_PRINTF */ /* compute the target of the call instruction which will be the * entry point (i.e., starting address) of the current function. * If the call was by a "jalr" instruction, then there is no way * to reconstruct the entry point since the register contents have * been lost. */ if (mips16Instructions((ULONG)callpc)) { callpc = (INSTR *)((int)callpc & ~0x1); if (M16_INSTR_OPCODE(*(UINT16 *)callpc) == M16_JALNX_INSTR) { ULONG dstAddr; dstAddr = ((*(UINT16 *)callpc) << 16) + (*((UINT16 *)callpc + 1)); dstAddr = M16_JALX_IMM(dstAddr) | (((ULONG)callpc) & 0xf0000000); return ( (INSTR *)dstAddr); } else return (NULL); } if (DSM (callpc, JAL_INSTR, GENERAL_OPCODE_MASK)) { /* Jump And Link -- target address specified by shifting the offset * left 2 bits and then "or"ing it with the upper 4 bits of the pc. */ return ( (INSTR *) (((*callpc & TARGET_MASK) << 2) | ((int) callpc & 0xf0000000)) ); } if (DSM (callpc,(BCOND | BLTZAL_INSTR), (GENERAL_OPCODE_MASK | BCOND_MASK)) || DSM (callpc,(BCOND | BGEZAL_INSTR), (GENERAL_OPCODE_MASK | BCOND_MASK)) || DSM (callpc,(BCOND | BLTZALL_INSTR), (GENERAL_OPCODE_MASK | BCOND_MASK)) || DSM (callpc,(BCOND | BGEZALL_INSTR), (GENERAL_OPCODE_MASK | BCOND_MASK))) { /* Branch And Link -- target address specified by shifting the * offset left 2 bits with sign extension and then adding it to the * address of the instruction in the delay slot. Note that the "C" * compiler automatically sign extends the "short" part of the * instruction (i.e., the lower 16 bits). */ return (callpc + 1 + (short) (*callpc & 0xFFFF)); } /* either the call was via a "jalr" or there was a bad instruction where * we thought we were called from */ return (NULL); }/****************************************************************************** trcGetFuncInfo - get address from which function was called** Determines specific info about the current function, such as the* address where it was called from, the stack frame size (if any) and* whether the stack frame has already been allocated.*/LOCAL void trcGetFuncInfo ( int depth, /* recursion depth */ REG_SET * regs, /* general purpose registers */ char * sp, /* stack pointer */ INSTR * pc, /* current pc */ INSTR ** pCallAddr, /* receives address from which this function called */ int * pFrameSize /* receives stack frame size */ ) { FAST int ix; FAST int scanDepth; FAST INSTR * scanpc; INSTR * retAddr; *pFrameSize = (int) 0; retAddr = (INSTR *) NULL;#ifdef DBG_PRINTF (void)printf("trcGetFuncInfo depth=%d pc=%08x sp=%08x\n", depth, pc, sp);#endif /* DBG_PRINTF */ /* scan instructions forward until the end of function or the max * scan count is reached. If we find a "sw ra,x(sp)" or a "jr ra" * then the return address in already in register "ra". If we find * a "lw ra,x(sp)" then the return address is saved in offset "x" * on the stack. If the instruction space is corrupted, could get * a bus error eventually or could find a return address for a * neighboring subprogram. The calling pc is determined by subtracting * 2 instructions from the return address. The stack frame size, if * found, and whether it is allocated, are passed out. */ /* check if the pc belongs to a mips16 function */ if (mips16Instructions((ULONG)pc)) { ULONG scanPc = (ULONG)pc & ~0x1; ULONG addr = (ULONG)NULL; for (ix = 0; ix < MAX_SCAN_DEPTH; ix++) { if (((*(UINT16 *)scanPc) & M16_I8_MASK) == M16_I8_SWRASP) { /* sw ra,x(sp) */ addr = regs->raReg; } else if ((*(UINT16 *)scanPc) == M16_JR_RA_INSTR) { /* jr ra */ if (addr == (ULONG)NULL) addr = regs->raReg; ix = MAX_SCAN_DEPTH - 2; } else if ((*(UINT16 *)scanPc) == M16_JR_A3_INSTR) { /* jr a3 */ if (addr == (ULONG)NULL) addr = regs->a3Reg; ix = MAX_SCAN_DEPTH - 2; } else if ((M16_INSTR_OPCODE(*(UINT16 *)scanPc) == M16_LWSP_INSTR) && (M16_RX(*(UINT16 *)scanPc) == M16_REG_7) ) { /* lw a3,x(sp) */ addr = *(ULONG *)((int)sp + *pFrameSize + M16_RI_OFFSET(*(UINT16 *)scanPc)); } else if (((*(UINT16 *)scanPc) & M16_I8_MASK) == M16_ADJSP_INSTR) { /* adjsp */ *pFrameSize += ((int)((*(UINT16 *)scanPc) & 0xff) << 24) >> 21; } scanPc += dsmNbytes(scanPc); } /* end for */ /* make sure address aligned at 2 byte boundary */ *pCallAddr = (INSTR *)((addr & ~0x1) - 6); return; } /* end if (mips16Instructions((ULONG)pc)) */ scanDepth = MAX_SCAN_DEPTH; if (depth == 0) { /* Check insn we're sitting on to see if we're at the first * instruction of the function */ if (DSM(pc, (ADDIU_INSTR | SP << RT_POS), (GENERAL_OPCODE_MASK | RT_MASK))) { /* match "[d]addiu sp,sp,-offset" * First instruction of function, innermost frame, don't scan. */ scanDepth = -1; retAddr = (INSTR*) ((int)regs->raReg); /* return point */ } else { /* If in innermost frame, don't disassemble instruction we're * sitting on, as we haven't executed it yet. */ scanDepth--; } } for (ix = scanDepth, scanpc = pc; ix >= 0; ix--, scanpc--) { /* match "jr ra" means ran off the top and missed the * beginning of the function. */ if (DSM(scanpc,(SPECIAL | JR_INSTR | RA << RS_POS), (GENERAL_OPCODE_MASK | SPECIAL_MASK | RS_MASK))) {#ifdef DBG_PRINTF (void)printf("trcGetFuncInfo depth=%d match jr ra\n", depth);#endif /* DBG_PRINTF */ /* If in innermost frame, assume return in ra. */ if (depth == 0) retAddr = (INSTR*) ((int)regs->raReg); /* return point */ break; } /* match "addiu sp,sp,+-offset" to determine stack frame size. * Note that the "C" compiler takes care of sign extension * from "short" to "int" when we extract the immediate part of * the instruction. */ else if (DSM(scanpc, (ADDIU_INSTR | SP << RT_POS), (GENERAL_OPCODE_MASK | RT_MASK))) {#ifdef DBG_PRINTF (void)printf("trcGetFuncInfo depth=%d match addiu sp,sp,+-offset\n", depth);#endif /* DBG_PRINTF */ if ((short)(*scanpc & 0xFFFF) > 0) { /* stack frame de-allocation implies we may have * run off the top of the function. Stop searching. */ if (retAddr == NULL) { retAddr = (INSTR*) ((int)regs->raReg); break; } } /* If we hit this before 'sw/sd ra,x(sp)', this means we're * stopped between the allocation of the stack frame and the * save of RA on the stack. If this happens anywhere other * than the innermost frame, it's illegal code and we're probabaly * actually lost. */ *pFrameSize -= (short)(*scanpc & 0xFFFF); /* get the immediate offset */ if ((depth == 0) && (retAddr == NULL)) { retAddr = (INSTR*) ((int)regs->raReg); break; } if (retAddr != NULL) { /* Have frameSize and retAddr, done with this frame. */ break; } }#if (CPU == MIPS64) /* match "sd ra,x(sp)" means return address is on the stack */ else if (DSM(scanpc,(SD_INSTR | RA << RT_POS | SP << BASE_POS), (GENERAL_OPCODE_MASK | RT_MASK | BASE_MASK))) {#ifdef DBG_PRINTF (void)printf("trcGetFuncInfo depth=%d sp=%08x scanpc=%08x match sd ra,x(sp)\n", depth,sp,*scanpc);#endif /* DBG_PRINTF */#if (_BYTE_ORDER == _BIG_ENDIAN) retAddr = (INSTR *) *(int *)((int)sp + (short)(*scanpc & 0xFFFF) + 4);#else /* (_BYTE_ORDER == _BIG_ENDIAN) */ retAddr = (INSTR *) *(int *)((int)sp + (short)(*scanpc & 0xFFFF));#endif /* (_BYTE_ORDER == _BIG_ENDIAN) */#ifdef DBG_PRINTF (void)printf("trcGetFuncInfo depth=%d retAddr=%08x\n", depth,retAddr);#endif /* DBG_PRINTF */ }#endif /* (CPU == MIPS64) */ /* match "sw ra,x(sp)" means return address is on the stack */ else if (DSM(scanpc,(SW_INSTR | RA << RT_POS | SP << BASE_POS), (GENERAL_OPCODE_MASK | RT_MASK | BASE_MASK))) {#ifdef DBG_PRINTF (void)printf("trcGetFuncInfo depth=%d sp=%08x scanpc=%08x match sw ra,x(sp)\n", depth,sp,*scanpc);#endif /* DBG_PRINTF */ retAddr = (INSTR *) *(int *)((int)sp + (short)(*scanpc & 0xFFFF));#ifdef DBG_PRINTF (void)printf("trcGetFuncInfo depth=%d retAddr=%08x\n", depth,retAddr);#endif /* DBG_PRINTF */ } } /* if a return address was found, subtract 2 instructions from it to * determine the calling point, or set it to NULL */ if (mips16Instructions((ULONG)retAddr) ) { /* Need to handle differently if it comes from a 16 bit function. * subtract 2 instructions: one 32 bit, jal(x) and one 16 bit delay slot */ if (retAddr != NULL) { retAddr = (INSTR *)(((int)retAddr & ~0x1) - 6); *pCallAddr = retAddr; } else *pCallAddr = NULL; } else *pCallAddr = (retAddr != NULL) ? (retAddr - 2) : NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -