CNktDvDbObjectNoRef::eCallingConvention CNktDvExportedFunction::GetCallingConvention() const { CNktDvDbObjectNoRef *_lpDbObj; _lpDbObj = GetFunctionEntry(); return (_lpDbObj != NULL) ? (lpDbObj->GetFuncCallingConvention()) : CNktDvDbObjectNoRef::ccNA; }
//PowerMac version of stack walking to find a C++ exception handler //Assume: // _pftinfo // void MacExceptionDispatch(PEXCEPTION_RECORD pExceptionRecord) { PPMSTACK spCur; PPMSTACK spCurCatch; DispatcherContext curDC; PRUNTIME_FUNCTION pFunctionEntry; PRUNTIME_FUNCTION pFunctionEntryCatch = NULL; PFTINFO pftinfoTOC; PPMSTACK pFrame; unsigned long cNestedTmp; PFRAMEINFO pframeinfo; spCur = (PMSTACK *)GetSP(); //Loop through the frames backwards on the stack to find a frame which has an EH handler //Assume: // End of Stack: when the save area link register is NULL // .pdata has Exception Handler points to CxxFrameHandler if an EH Frame // Exception Data points to FuncInfo spCur = spCur->pSpBackChain; //this should be in CxxThrowException frame spCur = spCur->pSpBackChain; //this should be in caller of CxxThrowException frame //Is this a cross TOC call? Do we need to switch RTOC???!!! if ( (spCur->dwLNKreg >= _pftinfo->dwEntryCF) && (spCur->dwLNKreg <= ((unsigned long)((char *)_pftinfo->dwEntryCF+ _pftinfo->dwSizeCF))) || spCur->dwTOCreg == (unsigned long)GetRTOC()) { // okay, we are throw in the same code fragment as CRT, CRT being statically linked in, or the same as last throw } else if ( (spCur->dwLNKreg >= _pftinfoCRT->dwEntryCF) && (spCur->dwLNKreg <= ((unsigned long)((char *)_pftinfoCRT->dwEntryCF+ _pftinfoCRT->dwSizeCF))) || spCur->dwTOCreg == (unsigned long)GetRTOC()) { _pftinfo = _pftinfoCRT; } else { // make _pftinfo point to the code fragment which has thrown the exception, CRT must be a DLL now _ASSERTE(spCur->dwTOCreg); _pftinfo = (PFTINFO)(*(unsigned long *)((char *)spCur->dwTOCreg + OFSFTINFO)); dwRTOC = spCur->dwTOCreg; } while (spCur->dwLNKreg) { if (_pFrameInfoChain) { // we should only look the outer nested scope for handlers and we should skip catch handler frame // because the actual frame called the catch handler is way down if ( (spCur > _pFrameInfoChain->pExitContext) && (spCur < _pFrameInfoChain->pSp) ) { spCur = spCur->pSpBackChain; continue; } if (cNested > 0) { cNestedTmp = cNested; pframeinfo = _pFrameInfoChain; while (cNestedTmp-- && pframeinfo) { // This means we are throw in the catch if ( (spCur->pSpBackChain == pframeinfo->pExitContext) ) { pFunctionEntryCatch = GetFunctionEntry(spCur, &pftinfoTOC); spCurCatch = spCur; break; } pframeinfo = pframeinfo->pNext; } if (pframeinfo) { spCur = spCur->pSpBackChain; continue; } } } pFunctionEntry = GetFunctionEntry(spCur, &pftinfoTOC); if (pFunctionEntry && (pFunctionEntry->ExceptionHandler != NULL)) { //stack point, old PC(in linker register, execution point==state), Registers in Context pFrame = spCur; curDC.ControlPc = spCur->dwLNKreg; curDC.FunctionEntry = pFunctionEntry; curDC.EstablisherFrame = spCur; curDC.pExcept = pExceptionRecord; if (_pftinfo != pftinfoTOC) { // we are calling catch which is in different code fragment curDC.pftinfo = pftinfoTOC; curDC.pftinfo->pFrameInfo = _pFrameInfoChain; _pftinfo->pFrameInfo = _pFrameInfoChain; _pFrameInfoChain = 0; //reset cNested = 0; } else { curDC.pftinfo = _pftinfo; curDC.pftinfo->pFrameInfo = _pFrameInfoChain; } if (dwRTOC == 0) { dwRTOC = (unsigned long)GetRTOC(); //not CRT as DLL case } //dwRTOC has throw object RTOC //curDC has handler's info if (pFunctionEntryCatch == pFunctionEntry) { // we have to update the return address in original catch frame if (spCurCatch->dwLNKreg > curDC.ControlPc) { curDC.ControlPc = spCurCatch->dwLNKreg; } //we have to remeber the current return from catch's throw, so we can unwinding properly. //the return in the frame is adjusted to next state, so it can be off for unwinding //Note: we only need all the trouble for statically nested case curDC.ControlPcOld = spCurCatch->dwLNKreg; fStaticNested = 1; } (*pFunctionEntry->ExceptionHandler)(pExceptionRecord, pFrame, (void *)dwRTOC, &curDC); if (_pftinfo != pftinfoTOC) { _pFrameInfoChain = (PFRAMEINFO)_pftinfo->pFrameInfo; //reset our globals if we come back;STILL problem!!! pframeinfo = _pFrameInfoChain; while (pframeinfo) { // This means we are throw in the catch cNested++; pframeinfo = pframeinfo->pNext; } } fStaticNested = 0; pFuncEntryLast = pFunctionEntry; } spCur = spCur->pSpBackChain; if (dwSPStartup) { if (spCur->dwLNKreg && (spCur > (PPMSTACK)dwSPStartup)) { //we are at second to last of stack frame, break out the loop break; } } else { // we don't know our bottom of stack, didn't go through this instance of mainCRTStartup // let's break out the loop if we encounter 68k frame if ((unsigned int)spCur & 0x01) { break; } } } //We don't have a handler, we should just exit out of the program terminate(); }
void _UnwindNestedFrames( EHRegistrationNode *pFrame, // Unwind up to (but not including) this frame EHExceptionRecord *pExcept // The exception that initiated this unwind //void *pContext // Context info for current exception ) { PPMSTACK spCur; PPMSTACK spCurCatch; DispatcherContext curDC; PFTINFO pftinfoTOC; PRUNTIME_FUNCTION pFunctionEntry; PRUNTIME_FUNCTION pFunctionEntryCatch = NULL; unsigned long cNestedTmp; PFRAMEINFO pframeinfo; spCur = (PPMSTACK)GetSP(); //Loop through the frames backwards on the stack to destroy objects until target frame //Assume: spCur = spCur->pSpBackChain; while (spCur < pFrame) { // we should only look the frame which hasn't been looked if (_pFrameInfoChain) { if ((spCur > _pFrameInfoChain->pExitContext) && (spCur < _pFrameInfoChain->pSp)) { spCur = spCur->pSpBackChain; continue; } if (cNested > 0) { cNestedTmp = cNested; pframeinfo = _pFrameInfoChain; while (cNestedTmp-- && pframeinfo) { if ( (spCur->pSpBackChain == pframeinfo->pExitContext) ) { pFunctionEntryCatch = GetFunctionEntry(spCur, &pftinfoTOC); spCurCatch = spCur; break; } pframeinfo = pframeinfo->pNext; } if (pframeinfo) { spCur = spCur->pSpBackChain; continue; } } } pFunctionEntry = GetFunctionEntry(spCur, &pftinfoTOC); if (pFunctionEntry && pFunctionEntry->ExceptionHandler != NULL) { //set unwinding flag //stack point, old PC(in linker register, execution point==state), Registers in Context PER_FLAGS(pExcept) |= EXCEPTION_UNWINDING; curDC.ControlPc = spCur->dwLNKreg; curDC.FunctionEntry = pFunctionEntry; //what else to save?! curDC.EstablisherFrame = spCur; curDC.pftinfo = pftinfoTOC; if (pFunctionEntryCatch == pFunctionEntry) { // we have to update the return address in original catch frame if (spCurCatch->dwLNKreg > curDC.ControlPc) { curDC.ControlPc = spCurCatch->dwLNKreg; } } (*pFunctionEntry->ExceptionHandler)(pExcept, spCur, NULL, &curDC); } spCur = spCur->pSpBackChain; } // // clear the unwinding flag, in case exception is rethown // PER_FLAGS(pExcept) &= ~EXCEPTION_UNWINDING; return; }