?? trclib.c
字號:
*/ static INSTR * trcFindFuncStart ( INSTR * pc, /* program counter within current proc */ INSTR * returnPc /* return address */ ) { INSTR * pInstr; int branchAddr; /* first check if there is a branch instruction before the returnPc */ pInstr = returnPc - 1; if ((INST_CMP (pInstr, INST_B, INST_B_MASK)) || (INST_CMP (pInstr, INST_BC, INST_B_MASK))) { /* extract address from instruction and sign extend */ if (INST_CMP (pInstr, INST_B, INST_B_MASK)) { branchAddr = *pInstr & 0x03fffffc; if (branchAddr & 0x02000000) branchAddr |= 0xfc000000; } else { branchAddr = *pInstr & 0xfffc; if (branchAddr & 0x8000) branchAddr |= 0xffff0000; } /* if branch is not absolute, add in relative address */ if (!_IFIELD_AA (*pInstr)) branchAddr += (int)pInstr; return ((INSTR *)branchAddr); } /* if that fails, try to scan backwards for "stwu sp, xxx(sp)" */ if (!BOGUS_PC(pc - trcScanDepth, pInstr)) { for (pInstr = pc; pInstr > pc - trcScanDepth; pInstr--) { if (INST_CMP (pInstr, INST_STWU_SP, INST_HIGH_MASK)) return (pInstr); } } /* if all else fails, return "pc" as a guess */ return (pc); }/******************************************************************************** trcPrologueFrameAllocated - check if stack frame is allocated** Start at "procAddr" and scan forwards up to MAX_PROLOGUE_SIZE instructions.* If we get to our PC before we see an "allocate stack frame" instruction,* then the current procedure does not have an allocated stack frame.** RETURNS: TRUE if frame is allocated, else false*/static BOOL trcPrologueFrameAllocated ( INSTR *procAddr, /* address of procedure */ INSTR *pc /* current PC value */ ) { INSTR *pInstr; for (pInstr = procAddr; pInstr < procAddr + MAX_PROLOGUE_SIZE; pInstr++) { if (INST_CMP (pInstr, INST_STWU_SP, INST_HIGH_MASK)) return (TRUE); if (pInstr == pc) return (FALSE); } return (TRUE); }/******************************************************************************** trcInfoGet - get info on top stack frame.** This routine grabs the stack pointer and pc from the register set.* It then computes the frame pointer and return PC.* The later two require care:* Usually both are on the stack.* Sometimes the return PC is in the link register. This is true in* a leaf procedure, or during a procedure prologue.* Sometimes the frame pointer is the stack pointer. This happens* when a frame has not been allocated for the current proc.* Leaf procedures often do not allocate stack frames. Non-leaf* procedures have no frames during the prologue and epilogue).* This procedure scans forward up to MAX_SCAN_DEPTH instructions from* the current PC looking for instructions that might give us a clue* as to which case we are in.* If the scan doesn't find any of the instructions is is looking for,* then it assumes we are in the normal case (frame allocated and* return PC saved to stack).* * XXX - If we are in a function epilogue and have just popped the* procedure frame, this routine will mistakenly skip the next* frame down.** A little sanity checking is done. If the stack pointer, frame pointer* PC or return PC are bogus, we return ERROR.** RETURNS: OK or ERROR if there was trouble parsing the frame.*/ static STATUS trcInfoGet ( int tid, /* task ID */ REG_SET * pRegs, /* task's registers */ INSTR ** pPc, /* return PC here */ INSTR ** pReturnPc, /* return calling PC here */ char ** pSp, /* return stack pointer here */ char ** pFp /* return frame pointer here */ ) { BOOL frameAllocated = TRUE; BOOL returnPcOnStack = TRUE; INSTR * pInstr; INSTR * pc; INSTR * procAddr; char * fp; char * sp; pc = (INSTR *)pRegs->pc; sp = (char *)pRegs->spReg; if (BOGUS_SP(sp, taskTcb(tid)->pStackEnd, taskTcb(tid)->pStackBase)) return (ERROR); if (BOGUS_PC(pc, pInstr)) goto skipscan; if (BOGUS_PC(pc + trcScanDepth, pInstr)) goto skipscan; /* Scan forward from current PC to see how the link register is used */ for (pInstr = pc; pInstr < pc + trcScanDepth; pInstr++) { /* mfspr lr,rx => in proc prologue with return PC in link register */ if (INST_CMP(pInstr, INST_MFLR, INST_MTSPR_MASK)) { procAddr = trcFindFuncStart (pc, (INSTR *)pRegs->lr); returnPcOnStack = FALSE; if (trcPrologueFrameAllocated(procAddr, pc)) frameAllocated = TRUE; else frameAllocated = FALSE; break; } /* bclr => in proc epilogue with return PC in link register */ if (INST_CMP(pInstr, INST_BCLR, INST_BCLR_MASK)) { returnPcOnStack = FALSE; frameAllocated = TRUE; /* XXX - not always true in epilogue */ break; } /* mtspr lr, rx => return PC in link register */ if (INST_CMP(pInstr, INST_MTLR, INST_MTSPR_MASK)) { returnPcOnStack = TRUE; frameAllocated = TRUE; /* XXX - not always true in epilogue */ break; } /* "stwu r1, rx" (but no mtspr lr, rx) */ if (INST_CMP (pInstr, INST_STWU_SP, INST_HIGH_MASK)) { returnPcOnStack = FALSE; frameAllocated = FALSE; break; } }skipscan: if (frameAllocated) { fp = FP_FROM_STACK (sp); if (BOGUS_SP (fp, sp, taskTcb(tid)->pStackBase)) return (ERROR); } else { fp = sp; /* no frame => sp=fp */ sp -= _STACK_ALIGN_SIZE; /* fake a stack pointer */ } /* store away the info */ *pPc = pc; *pSp = sp; *pFp = fp; if (returnPcOnStack) *pReturnPc = RETURN_PC_FROM_STACK (*pFp); else *pReturnPc = (INSTR *)pRegs->lr; if (BOGUS_PC(*pReturnPc, pInstr)) return (ERROR); return (OK); }/******************************************************************************** trcGetArgs - get function arguments from the stack.** XXX - No way to do this if the code is not compiled with "-g"* because the power PC calling conventions do not require* argumenst to be pushed on the stack.* This routine is based on disassembled GNU code, which contains* the following sequence near the proc prologue:** mfspr r0, LR # standard prologue* stw r31, 0xfffc(r1) # standard prologue* stw r0, 0x4(r1) # standard prologue* stwu r1, 0xffc0(r1) # standard prologue* or r31, r1, r1 # r31 = stack pointer* stw r3, 0x18(r31) # save arg0 0x18 bytes from sp* stw r4, 0x1c(r31) # save arg1 0x1c bytes from sp* stw r5, 0x20(r31) # save arg2 0x1c bytes from sp* ...** So we scan the function prologue looking for this pattern,* and if we find them we copy the args from the stack.* The ABI says nothing about this, so GNU or anouther compiler vendor* can change this at any time and break this stack tracer.** RETURNS: the number of arguments retrieved.*/ static int trcGetArgs ( INSTR *procAddr, char *sp, int *args ) { int nArgs = 0; INSTR *pInstr; for (pInstr = procAddr; pInstr < procAddr + MAX_PROLOGUE_SIZE; pInstr++) { if (INST_CMP (pInstr, STW(nArgs + 3), STW_REG_MASK)) { args[nArgs] = *(int *)(sp + (*pInstr & 0xffff)); nArgs++; if (nArgs >= MAX_TASK_ARGS) break; } /* a branch instuction means function prologue is over */ if (INST_CMP (pInstr, INST_BCLR, INST_BCLR_MASK) || INST_CMP (pInstr, INST_B, INST_B_MASK)) break; } return (nArgs); }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -