Annotation of mstools/samples/sdktools/image/drwatson/i386/walk.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1993  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     walk.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This file provides support for stack walking.
        !            12: 
        !            13: Author:
        !            14: 
        !            15:     Wesley Witt (wesw) 1-May-1993
        !            16: 
        !            17: Environment:
        !            18: 
        !            19:     User Mode
        !            20: 
        !            21: --*/
        !            22: 
        !            23: #include <windows.h>
        !            24: #include <stdlib.h>
        !            25: #include <stdio.h>
        !            26: #include <string.h>
        !            27: 
        !            28: #include "drwatson.h"
        !            29: #include "proto.h"
        !            30: 
        !            31: // prototypes
        !            32: 
        !            33: static BOOL ValidateReturnAddress ( DWORD dwRetAddr, PDEBUGPACKET dp );
        !            34: static DWORD GetReturnAddress (DWORD *pdwStackAddr, PDEBUGPACKET dp);
        !            35: static PFPO_DATA FindFpoDataForModule( DWORD dwPCAddr, PDEBUGPACKET dp );
        !            36: static PFPO_DATA SearchFpoData( DWORD key, PFPO_DATA base, DWORD num );
        !            37: static BOOL SetNonFpoFrameAddress( PSTACKWALK pstk, PDEBUGPACKET dp );
        !            38: 
        !            39: 
        !            40: 
        !            41: BOOL
        !            42: SetNonFpoFrameAddress( PSTACKWALK pstk, PDEBUGPACKET dp )
        !            43: {
        !            44:     DWORD       stack[4];
        !            45:     DWORD       dwRetAddr;
        !            46:     DWORD       dwStackAddr;
        !            47:     PFPO_DATA   pFpoData;
        !            48:     int         cb;
        !            49: 
        !            50: 
        !            51:     // read the first 2 dwords off the stack
        !            52:     if (!ReadProcessMemory( dp->hProcess,
        !            53:                             (LPVOID)pstk->frame,
        !            54:                             (LPVOID)stack,
        !            55:                             8,
        !            56:                             (LPDWORD)&cb )) {
        !            57:         return FALSE;
        !            58:     }
        !            59: 
        !            60:     // a previous function in the call stack was a fpo function that used ebp as
        !            61:     // a general purpose register.  ul contains the ebp value that was good  before
        !            62:     // that function executed.  it is that ebp that we want, not what was just read
        !            63:     // from the stack.  what was just read from the stack is totally bogus.
        !            64:     if (pstk->ul > 0) {
        !            65:         stack[0] = pstk->ul;
        !            66:         pstk->ul = 0;
        !            67:     }
        !            68:     pFpoData = FindFpoDataForModule(stack[1], dp);
        !            69:     pstk->pFpoData = pFpoData;
        !            70:     if (pFpoData) {
        !            71:         //--------------------------------------------
        !            72:         // this is the code for NON-FPO -> FPO frames
        !            73:         //--------------------------------------------
        !            74:         pstk->ul = stack[0];
        !            75:         pstk->frame += (pFpoData->cdwLocals * 4) + 8;
        !            76:         if (pFpoData->cbFrame == FRAME_FPO) {
        !            77:             pstk->frame += (pFpoData->cbRegs * 4);
        !            78:         }
        !            79:         // this necessary because we need to account for any parameters that
        !            80:         // were passed to the non-fpo function
        !            81:         if (pFpoData->cbFrame == FRAME_FPO) {
        !            82:             if (!ReadProcessMemory( dp->hProcess,
        !            83:                                     (LPVOID)pstk->frame,
        !            84:                                     (LPVOID)&stack[2],
        !            85:                                     8,
        !            86:                                     (LPDWORD)&cb )) {
        !            87:                 return FALSE;
        !            88:             }
        !            89:             if (!ValidateReturnAddress(stack[2], dp)) {
        !            90:                 dwStackAddr = pstk->frame;
        !            91:                 dwRetAddr = GetReturnAddress(&dwStackAddr, dp);
        !            92:                 if (dwRetAddr == 0) {
        !            93:                     return FALSE;
        !            94:                 }
        !            95:                 pstk->frame = dwStackAddr - 4;
        !            96:             }
        !            97:             else {
        !            98:                 pstk->frame -= 4;
        !            99:             }
        !           100:         }
        !           101:     }
        !           102:     else {
        !           103:         //------------------------------------------------
        !           104:         // this is the code for NON-FPO -> NON-FPO frames
        !           105:         //------------------------------------------------
        !           106:         pstk->pFpoData = 0;
        !           107: 
        !           108:         // dwSaveBP will be -1 when the first frame is being processed and the frame
        !           109:         // has not been setup (ie EBP has not been pushed).
        !           110:         if (pstk->ul < 0) {
        !           111:             pstk->frame = dp->tctx->frame;
        !           112:             pstk->ul = 0;
        !           113:         }
        !           114:         else {
        !           115:             pstk->frame = stack[0];
        !           116:         }
        !           117:     }
        !           118: 
        !           119:     // set the program counter to the return address
        !           120:     pstk->pc = stack[1];
        !           121:     return TRUE;
        !           122: }
        !           123: 
        !           124: 
        !           125: BOOL
        !           126: StackWalkNext( PSTACKWALK pstk, PDEBUGPACKET dp )
        !           127: {
        !           128:     DWORD          dwRetAddr;
        !           129:     DWORD          dwStackAddr;
        !           130:     DWORD          dwTemp;
        !           131:     DWORD          stack[2];
        !           132:     PFPO_DATA      pCpcFpoData;
        !           133:     PFPO_DATA      pRetFpoData;
        !           134:     int            cb;
        !           135: 
        !           136: 
        !           137:     // check to see if the current frame is an fpo frame
        !           138:     pCpcFpoData = FindFpoDataForModule(pstk->pc, dp);
        !           139:     if (pCpcFpoData) {
        !           140:         if (!ReadProcessMemory( dp->hProcess,
        !           141:                                 (LPVOID)pstk->frame,
        !           142:                                 (LPVOID)stack,
        !           143:                                 8,
        !           144:                                 (LPDWORD)&cb )) {
        !           145:             return FALSE;
        !           146:         }
        !           147:         dwRetAddr = stack[1];
        !           148:         // is EBP used as a general purpose register in the function?
        !           149:         if (pCpcFpoData->fUseBP == 1) {
        !           150:             // backup and get the ebp register off the stack
        !           151:             pstk->frame -= (pCpcFpoData->cdwLocals * 4) -
        !           152:                             ((pCpcFpoData->cbRegs - 1) * 4);
        !           153:             if (!ReadProcessMemory( dp->hProcess,
        !           154:                                     (LPVOID)pstk->frame,
        !           155:                                     (LPVOID)&pstk->ul,
        !           156:                                     4,
        !           157:                                     (LPDWORD)&cb )) {
        !           158:                 return FALSE;
        !           159:             }
        !           160:             pstk->frame += (pCpcFpoData->cdwLocals * 4) -
        !           161:                            ((pCpcFpoData->cbRegs - 1) * 4);
        !           162:         }
        !           163:         // account for parameters and the current frame
        !           164:         pstk->frame += (pCpcFpoData->cdwParams * 4) + 8;
        !           165:         // check to see if the next frame is an fpo frame
        !           166:         pRetFpoData = FindFpoDataForModule(dwRetAddr, dp);
        !           167:         if (pRetFpoData) {
        !           168:             //-----------------------------------------
        !           169:             // this is the code for FPO -> FPO frames
        !           170:             //-----------------------------------------
        !           171:             pstk->frame += (pRetFpoData->cdwLocals * 4);
        !           172:             pstk->pFpoData = pRetFpoData;
        !           173:             if (pRetFpoData->cbFrame == FRAME_FPO) {
        !           174:                 pstk->frame += (pRetFpoData->cbRegs * 4);
        !           175:                 // this necessary because of registers that may have been saved
        !           176:                 // that we don't know about
        !           177:                 dwStackAddr = pstk->frame;
        !           178:                 dwTemp = GetReturnAddress(&dwStackAddr, dp);
        !           179:                 if (dwTemp == 0) {
        !           180:                     return FALSE;
        !           181:                 }
        !           182:                 pstk->frame = dwStackAddr - 4;
        !           183:             }
        !           184:         }
        !           185:         else {
        !           186:             //--------------------------------------------
        !           187:             // this is the code for FPO -> NON-FPO frames
        !           188:             //--------------------------------------------
        !           189:             pstk->pFpoData = 0;
        !           190:             if (pCpcFpoData->fUseBP == 1) {
        !           191:                 pstk->frame = pstk->ul;
        !           192:                 pstk->ul = 0;
        !           193:             }
        !           194:             else
        !           195:             if (pstk->ul != 0) {
        !           196:                 pstk->frame = pstk->ul;
        !           197:                 pstk->ul = 0;
        !           198:             }
        !           199:         }
        !           200:         pstk->pc = dwRetAddr;
        !           201:     }
        !           202:     else {
        !           203:         if (!SetNonFpoFrameAddress( pstk, dp )) {
        !           204:             return FALSE;
        !           205:         }
        !           206:     }
        !           207: 
        !           208:     // this is what should normally stop the stack walk
        !           209:     if (!ValidateReturnAddress(pstk->pc, dp)) {
        !           210:         return FALSE;
        !           211:     }
        !           212: 
        !           213:     if (!ReadProcessMemory( dp->hProcess,
        !           214:                             (LPVOID)(pstk->frame+8),
        !           215:                             (LPVOID)pstk->params,
        !           216:                             16,
        !           217:                             (LPDWORD)&cb )) {
        !           218:         return FALSE;
        !           219:     }
        !           220: 
        !           221:     return TRUE;
        !           222: }
        !           223: 
        !           224: 
        !           225: BOOL
        !           226: StackWalkInit( PSTACKWALK pstk, PDEBUGPACKET dp )
        !           227: {
        !           228:     UCHAR               code[3];
        !           229:     PFPO_DATA           pFpoData;
        !           230:     int                 cb;
        !           231:     PMODULEINFO         mi;
        !           232: 
        !           233: 
        !           234:     pstk->pc = dp->tctx->pc;
        !           235: 
        !           236:     pFpoData = FindFpoDataForModule(pstk->pc, dp);
        !           237:     pstk->pFpoData = pFpoData;
        !           238:     if (pFpoData) {
        !           239:         pstk->frame = dp->tctx->stack;
        !           240:         mi = GetModuleForPC( dp, dp->tctx->pc );
        !           241:         if (mi == NULL) {
        !           242:             return FALSE;
        !           243:         }
        !           244:         if (dp->tctx->pc == mi->dwLoadAddress+pFpoData->ulOffStart) {
        !           245:             // first byte of code
        !           246:             pstk->frame -= 4;
        !           247:             pstk->ul = dp->tctx->frame;
        !           248:         }
        !           249:         else {
        !           250:             // somewhere in the body
        !           251:             pstk->frame += (pFpoData->cdwLocals * 4);
        !           252:             if (pFpoData->cbRegs != 7) {
        !           253:                 pstk->frame += (pFpoData->cbRegs * 4);
        !           254:             }
        !           255:             pstk->frame -= 4;
        !           256:             if (pFpoData->fUseBP == 1) {
        !           257:                 // the last item pushed onto the stack was EBP
        !           258:                 if (!ReadProcessMemory( dp->hProcess,
        !           259:                                         (LPVOID)pstk->frame,
        !           260:                                         (LPVOID)&pstk->ul,
        !           261:                                         4,
        !           262:                                         (LPDWORD)&cb )) {
        !           263:                     return FALSE;
        !           264:                 }
        !           265:             }
        !           266:             else {
        !           267:                 pstk->ul = dp->tctx->frame;
        !           268:             }
        !           269:         }
        !           270:     }
        !           271:     else {
        !           272:         pstk->ul = 0;
        !           273:         if (!ReadProcessMemory( dp->hProcess,
        !           274:                                 (LPVOID)pstk->pc,
        !           275:                                 (LPVOID)code,
        !           276:                                 3,
        !           277:                                 (LPDWORD)&cb )) {
        !           278:             return FALSE;
        !           279:         }
        !           280:         if ((code[0] == 0x55) || (code[0] == 0x8b && code[1] == 0xec)) {
        !           281:             pstk->frame = dp->tctx->stack;
        !           282:             if (code[0] == 0x55) {
        !           283:                 pstk->frame -= 4;
        !           284:                 pstk->ul = -1;
        !           285:             }
        !           286:         }
        !           287:         else {
        !           288:             pstk->frame = dp->tctx->frame;
        !           289:         }
        !           290:     }
        !           291: 
        !           292:     if (!ReadProcessMemory( dp->hProcess,
        !           293:                             (LPVOID)(pstk->frame+8),
        !           294:                             (LPVOID)pstk->params,
        !           295:                             16,
        !           296:                             (LPDWORD)&cb )) {
        !           297:         return FALSE;
        !           298:     }
        !           299: 
        !           300:     return TRUE;
        !           301: }
        !           302: 
        !           303: PFPO_DATA
        !           304: SearchFpoData( DWORD key, PFPO_DATA base, DWORD num )
        !           305: {
        !           306:     PFPO_DATA  lo = base;
        !           307:     PFPO_DATA  hi = base + (num - 1);
        !           308:     PFPO_DATA  mid;
        !           309:     DWORD      half;
        !           310: 
        !           311:     while (lo <= hi) {
        !           312:             if (half = num / 2) {
        !           313:                     mid = lo + (num & 1 ? half : (half - 1));
        !           314:                     if ((key >= mid->ulOffStart)&&(key < (mid->ulOffStart+mid->cbProcSize))) {
        !           315:                         return mid;
        !           316:                     }
        !           317:                     if (key < mid->ulOffStart) {
        !           318:                             hi = mid - 1;
        !           319:                             num = num & 1 ? half : half-1;
        !           320:                     }
        !           321:                     else {
        !           322:                             lo = mid + 1;
        !           323:                             num = half;
        !           324:                     }
        !           325:             }
        !           326:             else
        !           327:             if (num) {
        !           328:                 if ((key >= lo->ulOffStart)&&(key < (lo->ulOffStart+lo->cbProcSize))) {
        !           329:                     return lo;
        !           330:                 }
        !           331:                 else {
        !           332:                     break;
        !           333:                 }
        !           334:             }
        !           335:             else {
        !           336:                     break;
        !           337:             }
        !           338:     }
        !           339:     return(NULL);
        !           340: }
        !           341: 
        !           342: PFPO_DATA
        !           343: FindFpoDataForModule( DWORD dwPCAddr, PDEBUGPACKET dp )
        !           344: {
        !           345:     PMODULEINFO         mi;
        !           346:     PFPO_DATA           pFpoData;
        !           347: 
        !           348:     mi = GetModuleForPC( dp, dwPCAddr );
        !           349: 
        !           350:     /*
        !           351:      * If the address was not found in any dll then return FALSE
        !           352:      */
        !           353: 
        !           354:     if (mi == NULL) {
        !           355:         return FALSE;
        !           356:     }
        !           357: 
        !           358:     if (!mi->pFpoData) {
        !           359:         return FALSE;
        !           360:     }
        !           361: 
        !           362:     /*
        !           363:      * Search for the PC in the fpo data
        !           364:      */
        !           365:     dwPCAddr -= mi->dwLoadAddress;
        !           366:     pFpoData = SearchFpoData( dwPCAddr, mi->pFpoData, mi->dwEntries );
        !           367:     return pFpoData;
        !           368: }
        !           369: 
        !           370: DWORD
        !           371: GetReturnAddress (DWORD *pdwStackAddr, PDEBUGPACKET dp )
        !           372: {
        !           373:     DWORD       stack[64];
        !           374:     DWORD       i, sw;
        !           375: 
        !           376:     sw = 64*4;
        !           377:     if(!ReadProcessMemory(dp->hProcess, (LPVOID)*pdwStackAddr, (LPVOID)stack, sw, &sw)) {
        !           378:         sw = 0xFFF - (*pdwStackAddr & 0xFFF);
        !           379:         if(!ReadProcessMemory(dp->hProcess, (LPVOID)*pdwStackAddr, (LPVOID)stack, sw, &sw)) {
        !           380:             return 0;
        !           381:         }
        !           382:     }
        !           383:     // scan thru the stack looking for a return address
        !           384:     for (i=0; i<sw/4; i++) {
        !           385:         if (ValidateReturnAddress(stack[i], dp)) {
        !           386:             *pdwStackAddr += (i * 4);
        !           387:             return stack[i];
        !           388:         }
        !           389:     }
        !           390:     return 0;
        !           391: }
        !           392: 
        !           393: BOOL
        !           394: ValidateReturnAddress ( DWORD dwRetAddr, PDEBUGPACKET dp )
        !           395: {
        !           396:     PMODULEINFO mi;
        !           397: 
        !           398:     mi = GetModuleForPC( dp, dwRetAddr );
        !           399: 
        !           400:     if (mi == NULL) {
        !           401:         return FALSE;
        !           402:     }
        !           403: 
        !           404:     return TRUE;
        !           405: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.