Leaked source code of windows server 2003
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
#include <windows.h>
#include <stdio.h>
#include "view.h"
#include "except.h"
#include "disasm.h"
#include "dump.h"
#include "profiler.h"
#include "memory.h"
#include "filter.h"
static PVIEWCHAIN *ppViewHead = 0; static CRITICAL_SECTION viewCritSec; static CRITICAL_SECTION mapCritSec; static PTAGGEDADDRESS pTagHead = 0; static PBRANCHADDRESS pBranchHead = 0;
BOOL InitializeViewData(VOID) { InitializeCriticalSection(&viewCritSec); InitializeCriticalSection(&mapCritSec);
//
// Allocate hashing data
//
ppViewHead = (PVIEWCHAIN *)AllocMem(sizeof(PVIEWCHAIN) * (MAX_MAP_SIZE >> MAP_STRIDE_BITS)); if (0 == ppViewHead) { return FALSE; }
return TRUE; }
PVIEWCHAIN AddViewToMonitor(DWORD dwAddress, BPType bpType) { PVIEWCHAIN pView; DWORD dwHash;
//
// If address is higher than the map size, fail it
//
if (dwAddress >= MAX_MAP_SIZE) { return 0; }
//
// This occurs when a call tries to map over an existing trace breakpoint
//
if (*(BYTE *)dwAddress == X86_BREAKPOINT) { return 0; }
//
// Check if we're filtering this address
//
if (TRUE == IsAddressFiltered(dwAddress)) { return 0; }
//
// Allocate a chain entry
//
pView = AllocMem(sizeof(VIEWCHAIN)); if (0 == pView) { return 0; }
pView->bMapped = FALSE; pView->bTraced = FALSE; pView->dwAddress = dwAddress; pView->dwMapExtreme = dwAddress; pView->jByteReplaced = *(BYTE *)dwAddress; pView->bpType = bpType;
//
// Set a breakpoint at the top of the code
//
WRITEBYTE(dwAddress, X86_BREAKPOINT);
EnterCriticalSection(&viewCritSec);
//
// Add view point to monitor list
//
dwHash = dwAddress >> MAP_STRIDE_BITS; if (0 == ppViewHead[dwHash]) { ppViewHead[dwHash] = pView; } else { //
// Chain to head
//
pView->pNext = ppViewHead[dwHash]; ppViewHead[dwHash] = pView; }
LeaveCriticalSection(&viewCritSec);
return pView; }
PVIEWCHAIN RestoreAddressFromView(DWORD dwAddress, BOOL bResetData) { BOOL bResult = FALSE; PVIEWCHAIN pTemp;
EnterCriticalSection(&viewCritSec);
pTemp = ppViewHead[dwAddress >> MAP_STRIDE_BITS]; while (pTemp) { //
// Is this our entry
//
if (dwAddress == pTemp->dwAddress) { //
// Set a breakpoint at the top of the code
//
if (TRUE == bResetData) { WRITEBYTE(dwAddress, pTemp->jByteReplaced); } else { WRITEBYTE(dwAddress, X86_BREAKPOINT); }
//
// Return with modified data
//
break; }
pTemp = pTemp->pNext; }
LeaveCriticalSection(&viewCritSec); return pTemp; }
PVIEWCHAIN FindView(DWORD dwAddress) { PVIEWCHAIN pTemp;
if (dwAddress >= MAX_MAP_SIZE) { return 0; }
EnterCriticalSection(&viewCritSec);
pTemp = ppViewHead[dwAddress >> MAP_STRIDE_BITS]; while (pTemp) { //
// See if address is mapped
//
if (dwAddress == pTemp->dwAddress) { LeaveCriticalSection(&viewCritSec);
return pTemp; }
pTemp = pTemp->pNext; }
LeaveCriticalSection(&viewCritSec);
return 0; }
BOOL MapCode(PVIEWCHAIN pvMap) { BOOL bResult; DWORD dwCurrent; DWORD *pdwAddress; DWORD *pdwTemp; PCHAR pCode; PVIEWCHAIN pvTemp; DWORD dwLength; DWORD dwJumpEIP; LONG lOffset; DWORD dwInsLength; DWORD dwTemp; BYTE tempCode[32]; BYTE jOperand; DWORD dwProfileEnd = 0; CHAR szBuffer[MAX_PATH];
//
// Map termination through all conditionals
//
dwCurrent = pvMap->dwAddress;
//
// Take the mapping lock
//
LockMapper();
//
// Forward scan through code to find termination
//
while(1) { strncpy(tempCode, (PCHAR)dwCurrent, 32);
//
// Make sure the instruction is unmodified
//
if (tempCode[0] == (BYTE)X86_BREAKPOINT) { //
// Rebuild instruction without breakpoints
//
pvTemp = FindView(dwCurrent); if (pvTemp) { //
// Replace the bytes if we have a match
//
tempCode[0] = pvTemp->jByteReplaced; } }
//
// Calculate instruction length
//
dwInsLength = GetInstructionLengthFromAddress((PVOID)tempCode);
//
// Follow a forward trace through jumps to the ret
//
if ((tempCode[0] >= (BYTE)0x70) && (tempCode[0] <= (BYTE)0x7f)) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Relative branch
//
dwJumpEIP = (dwCurrent + 2 + (CHAR)(tempCode[1]));
//
// Mark this branch as executed
//
bResult = AddTaggedAddress(dwCurrent); if (FALSE == bResult) { return FALSE; }
if (dwJumpEIP > dwCurrent) { //
// Push the opposite branch
//
bResult = PushBranch(dwCurrent + dwInsLength); if (FALSE == bResult) { return FALSE; }
dwCurrent = dwJumpEIP; } else { //
// Push the opposite branch
//
bResult = PushBranch(dwJumpEIP); if (FALSE == bResult) { return FALSE; }
dwCurrent += dwInsLength; }
continue; }
if (tempCode[0] == (BYTE)0x0f) { if ((tempCode[1] >= (BYTE)0x80) && (tempCode[1] <= (BYTE)0x8f)) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Relative branch
//
dwJumpEIP = (dwCurrent + 6 + *(LONG *)(&(tempCode[2])));
//
// Mark this branch as executed
//
bResult = AddTaggedAddress(dwCurrent); if (FALSE == bResult) { return FALSE; }
if (dwJumpEIP > dwCurrent) { //
// Push the opposite branch
//
bResult = PushBranch(dwCurrent + dwInsLength); if (FALSE == bResult) { return FALSE; } dwCurrent = dwJumpEIP; } else { //
// Push the opposite branch
//
bResult = PushBranch(dwJumpEIP); if (FALSE == bResult) { return FALSE; }
dwCurrent += dwInsLength; }
continue; } }
if (tempCode[0] == (BYTE)0xe3) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Relative branch
//
dwJumpEIP = (dwCurrent + 2 + (CHAR)(tempCode[1]));
//
// Mark this branch as executed
//
bResult = AddTaggedAddress(dwCurrent); if (FALSE == bResult) { return FALSE; }
if (dwJumpEIP > dwCurrent) { //
// Push the opposite branch
//
bResult = PushBranch(dwCurrent + dwInsLength); if (FALSE == bResult) { return FALSE; }
dwCurrent = dwJumpEIP; } else { //
// Push the opposite branch
//
bResult = PushBranch(dwJumpEIP); if (FALSE == bResult) { return FALSE; }
dwCurrent += dwInsLength; }
continue; }
if (tempCode[0] == (BYTE)0xeb) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Jump relative
//
dwJumpEIP = (dwCurrent + 2 + (CHAR)(tempCode[1]));
//
// Mark this branch as executed
//
bResult = AddTaggedAddress(dwCurrent); if (FALSE == bResult) { return FALSE; } //
// Jmp must always be followed
//
dwCurrent = dwJumpEIP; continue; }
if (tempCode[0] == (BYTE)0xe9) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Jump relative
//
dwJumpEIP = (dwCurrent + 5 + *(LONG *)(&(tempCode[1])));
//
// Mark this branch as executed
//
bResult = AddTaggedAddress(dwCurrent); if (FALSE == bResult) { return FALSE; } //
// Jump must always be followed
//
dwCurrent = dwJumpEIP; continue; } //
// Probe for calls and jumps
//
if (tempCode[0] == (BYTE)0xff) { //
// Tests for whether this is a call or not
//
jOperand = (tempCode[1] >> 3) & 7; if ((jOperand == 2) || (jOperand == 3) || (jOperand == 4) || (jOperand == 5)) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Add our mapping breakpoint with the appropriate type
//
if ((jOperand == 2) || (jOperand == 3)) { pvTemp = AddViewToMonitor(dwCurrent, Call); if (pvTemp) { pvTemp->bMapped = TRUE; } } else { //
// These kinds of jumps are always a break (there's no way to forward trace them)
//
pvTemp = AddViewToMonitor(dwCurrent, Jump); if (pvTemp) { pvTemp->bMapped = TRUE; } else { //
// Special case for mapping breakpoints which really are just jumps
//
pvTemp = FindView(dwCurrent); if (pvTemp) { pvTemp->bMapped = TRUE; pvTemp->bpType = Jump; } } //
// Mark this branch as executed
//
bResult = AddTaggedAddress(dwCurrent); if (FALSE == bResult) { return FALSE; }
//
// Dump the tree
//
dwTemp = PopBranch(); if (dwTemp) { dwCurrent = dwTemp; continue; }
break; } } }
if (tempCode[0] == (BYTE)0xe8) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Add this top call to the view
//
pvTemp = AddViewToMonitor(dwCurrent, Call); if (pvTemp) { pvTemp->bMapped = TRUE; } }
if (tempCode[0] == (BYTE)0x9a) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Add this top call to the view
//
pvTemp = AddViewToMonitor(dwCurrent, Call); if (pvTemp) { pvTemp->bMapped = TRUE; } }
if (tempCode[0] == (BYTE)0xea) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// Absolute far jumps are a terminating condition - flush all branches
//
pvTemp = AddViewToMonitor(dwCurrent, Jump); if (pvTemp) { pvTemp->bMapped = TRUE; } //
// Mark this branch as executed
//
bResult = AddTaggedAddress(dwCurrent); if (FALSE == bResult) { return FALSE; }
//
// Dump the tree
//
dwTemp = PopBranch(); if (dwTemp) { dwCurrent = dwTemp; continue; }
break; }
if (*(WORD *)(&(tempCode[0])) == 0xffff) { //
// Update the end of the region marker
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; }
//
// This is also a trace path terminator - see if we need to trace more conditions
//
dwTemp = PopBranch(); if (dwTemp) { //
// We have a branch to follow
//
dwCurrent = dwTemp; continue; }
//
// Update the end of the address range
//
break; }
if (tempCode[0] == (BYTE)0xc3) { //
// This is also a trace path terminator - see if we need to trace more conditions
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; } dwTemp = PopBranch(); if (dwTemp) { //
// We have a branch to follow
//
dwCurrent = dwTemp; continue; }
break; }
if (tempCode[0] == (BYTE)0xc2) { //
// This is also a trace path terminator - see if we need to trace more conditions
//
if (dwCurrent > dwProfileEnd) { dwProfileEnd = dwCurrent; } dwTemp = PopBranch(); if (dwTemp) { //
// We have a branch to follow
//
dwCurrent = dwTemp; continue; }
break; }
dwCurrent += dwInsLength; }
if (dwProfileEnd) { pvMap->dwMapExtreme = dwProfileEnd; } else { pvMap->dwMapExtreme = dwCurrent; }
bResult = WriteMapInfo(pvMap->dwAddress, pvMap->dwMapExtreme); if (!bResult) { return FALSE; }
//
// Restore the code we've whacked around
//
bResult = RestoreTaggedAddresses(); if (FALSE == bResult) { return FALSE; }
//
// Assert if this _ever_ happens
//
if (pBranchHead != 0) { Sleep(20000); _asm int 3 }
//
// We're mapped
//
pvMap->bMapped = TRUE;
//
// Release the mapping lock
//
UnlockMapper();
return TRUE; }
//
// Trace helpers
//
BOOL AddTaggedAddress(DWORD dwAddress) { PTAGGEDADDRESS pTagTemp; DWORD dwTempAddress;
//
// Make sure we haven't addressed this tag
//
if (*(WORD *)dwAddress == 0xFFFF) { //
// No need since it's already tagged
//
return TRUE; }
//
// Store off the bytes we are tagging
//
pTagTemp = AllocMem(sizeof(TAGGEDADDRESS)); if (0 == pTagTemp) { return FALSE; }
pTagTemp->dwAddress = dwAddress; pTagTemp->wBytesReplaced = *(WORD *)dwAddress;
//
// Chain the entry
//
if (0 == pTagHead) { pTagHead = pTagTemp; } else { pTagTemp->pNext = pTagHead; pTagHead = pTagTemp; }
//
// Mark this branch as executed
//
WRITEWORD(dwAddress, 0xFFFF); return TRUE; }
BOOL RestoreTaggedAddresses(VOID) { PTAGGEDADDRESS pTagTemp; PTAGGEDADDRESS pTagTemp2;
//
// Walk the tag list and replace the marked branches with their original bytes
//
pTagTemp = pTagHead; while(pTagTemp) { //
// Dirty up the code now so the branches can auto terminate
//
WRITEWORD(pTagTemp->dwAddress, pTagTemp->wBytesReplaced);
pTagTemp2 = pTagTemp;
pTagTemp = pTagTemp->pNext;
//
// Dump the old allocated memory
//
FreeMem(pTagTemp2); }
pTagHead = 0; return TRUE; }
BOOL PushBranch(DWORD dwAddress) { PBRANCHADDRESS pBranchTemp;
pBranchTemp = AllocMem(sizeof(BRANCHADDRESS)); if (0 == pBranchTemp) { return FALSE; }
pBranchTemp->dwAddress = dwAddress;
if (0 == pBranchHead) { pBranchHead = pBranchTemp; } else { pBranchTemp->pNext = pBranchHead; pBranchHead = pBranchTemp; }
return TRUE; }
DWORD PopBranch(VOID) { PBRANCHADDRESS pBranchTemp; DWORD dwAddress = 0;
pBranchTemp = pBranchHead;
if (0 == pBranchTemp) { return 0; }
dwAddress = pBranchTemp->dwAddress; pBranchHead = pBranchHead->pNext;
FreeMem(pBranchTemp);
return dwAddress; }
VOID LockMapper(VOID) { EnterCriticalSection(&mapCritSec); }
VOID UnlockMapper(VOID) { LeaveCriticalSection(&mapCritSec); }
|