233 lines
4.8 KiB
C++
233 lines
4.8 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (C) 1996-2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
STACKCOM.CPP
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
stack implementation.
|
||
|
|
||
|
History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include <stdio.h>
|
||
|
|
||
|
|
||
|
#ifdef _MT
|
||
|
#undef _MT
|
||
|
#include <yvals.h>
|
||
|
#define _MT
|
||
|
#endif
|
||
|
|
||
|
#include "arena.h"
|
||
|
|
||
|
#include "sync.h"
|
||
|
#include "flexarry.h"
|
||
|
#include <time.h>
|
||
|
#include <stdio.h>
|
||
|
#include <arrtempl.h>
|
||
|
#include <sync.h>
|
||
|
#include <malloc.h>
|
||
|
#include <imagehlp.h>
|
||
|
#include <execq.h>
|
||
|
#include "stackcom.h"
|
||
|
|
||
|
void* CStackRecord::mstatic_apReturns[1000];
|
||
|
|
||
|
void CStackRecord::Create(int nIgnore, BOOL bStatic)
|
||
|
{
|
||
|
m_dwNumItems = GetStackLen() - nIgnore;
|
||
|
if(bStatic)
|
||
|
{
|
||
|
m_apReturns = (void**)mstatic_apReturns;
|
||
|
m_bDelete = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_apReturns = new void*[m_dwNumItems];
|
||
|
m_bDelete = TRUE;
|
||
|
}
|
||
|
|
||
|
ReadStack(nIgnore, m_apReturns);
|
||
|
}
|
||
|
|
||
|
CStackRecord::~CStackRecord()
|
||
|
{
|
||
|
if(m_bDelete)
|
||
|
delete m_apReturns;
|
||
|
}
|
||
|
|
||
|
void CStackRecord::MakeCopy(CStackRecord& Other)
|
||
|
{
|
||
|
m_dwNumItems = Other.GetNumItems();
|
||
|
DWORD dwLen = Other.GetNumItems() * sizeof(void*);
|
||
|
m_apReturns = new void*[Other.GetNumItems()];
|
||
|
memcpy(m_apReturns, Other.GetItems(), dwLen);
|
||
|
m_bDelete = TRUE;
|
||
|
}
|
||
|
|
||
|
int CStackRecord::Compare(const CStackRecord& Other) const
|
||
|
{
|
||
|
int nDiff = GetNumItems()- Other.GetNumItems();
|
||
|
if(nDiff)
|
||
|
return nDiff;
|
||
|
|
||
|
return memcmp(GetItems(), Other.GetItems(), sizeof(void*) * GetNumItems());
|
||
|
}
|
||
|
|
||
|
DWORD CStackRecord::GetStackLen()
|
||
|
{
|
||
|
void* pFrame;
|
||
|
__asm
|
||
|
{
|
||
|
mov pFrame, ebp
|
||
|
}
|
||
|
|
||
|
CStackContinuation* pPrev = CStackContinuation::Get();
|
||
|
void* pEnd = NULL;
|
||
|
if(pPrev)
|
||
|
pEnd = pPrev->m_pThisStackEnd;
|
||
|
|
||
|
DWORD dwLen = 0;
|
||
|
while(!IsBadReadPtr(pFrame, sizeof(DWORD)))
|
||
|
{
|
||
|
dwLen++;
|
||
|
void** ppReturn = (void**)pFrame + 1;
|
||
|
void* pReturn = *ppReturn;
|
||
|
if(pReturn == pEnd)
|
||
|
break;
|
||
|
void* pNewFrame = *(void**)pFrame;
|
||
|
if(pNewFrame <= pFrame)
|
||
|
break;
|
||
|
pFrame = pNewFrame;
|
||
|
}
|
||
|
|
||
|
if(pPrev != NULL)
|
||
|
dwLen += pPrev->m_pPrevStack->GetNumItems();
|
||
|
|
||
|
return dwLen;
|
||
|
}
|
||
|
|
||
|
void CStackRecord::ReadStack(int nIgnore, void** apReturns)
|
||
|
{
|
||
|
void* pFrame;
|
||
|
__asm
|
||
|
{
|
||
|
mov pFrame, ebp
|
||
|
}
|
||
|
|
||
|
CStackContinuation* pPrev = CStackContinuation::Get();
|
||
|
void* pEnd = NULL;
|
||
|
if(pPrev)
|
||
|
pEnd = pPrev->m_pThisStackEnd;
|
||
|
|
||
|
while(!IsBadReadPtr(pFrame, sizeof(DWORD)))
|
||
|
{
|
||
|
void** ppReturn = (void**)pFrame + 1;
|
||
|
void* pReturn = *ppReturn;
|
||
|
if(pReturn == pEnd)
|
||
|
break;
|
||
|
|
||
|
if(nIgnore == 0)
|
||
|
*(apReturns++) = pReturn;
|
||
|
else
|
||
|
nIgnore--;
|
||
|
|
||
|
void* pNewFrame = *(void**)pFrame;
|
||
|
if(pNewFrame <= pFrame)
|
||
|
break;
|
||
|
pFrame = pNewFrame;
|
||
|
}
|
||
|
|
||
|
if(pPrev != NULL)
|
||
|
{
|
||
|
memcpy(apReturns, pPrev->m_pPrevStack->m_apReturns,
|
||
|
sizeof(void*) * pPrev->m_pPrevStack->GetNumItems());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CStackRecord::Dump(FILE* f) const
|
||
|
{
|
||
|
fwrite(&m_dwNumItems, sizeof(DWORD), 1, f);
|
||
|
fwrite(m_apReturns, sizeof(void*), m_dwNumItems, f);
|
||
|
}
|
||
|
|
||
|
BOOL CStackRecord::Read(FILE* f, BOOL bStatic)
|
||
|
{
|
||
|
if(fread(&m_dwNumItems, sizeof(DWORD), 1, f) == 0)
|
||
|
return FALSE;
|
||
|
|
||
|
if(bStatic)
|
||
|
{
|
||
|
m_apReturns = (void**)mstatic_apReturns;
|
||
|
m_bDelete = FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_apReturns = new void*[m_dwNumItems];
|
||
|
m_bDelete = TRUE;
|
||
|
}
|
||
|
|
||
|
return (fread(m_apReturns, sizeof(void*), m_dwNumItems, f) != 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void CAllocRecord::Dump(FILE* f) const
|
||
|
{
|
||
|
fwrite(&m_dwTotalAlloc, sizeof(DWORD), 1, f);
|
||
|
fwrite(&m_dwNumTimes, sizeof(DWORD), 1, f);
|
||
|
m_Stack.Dump(f);
|
||
|
DWORD dwNumBuffers = m_apBuffers.Size();
|
||
|
fwrite(&dwNumBuffers, sizeof(DWORD), 1, f);
|
||
|
fwrite(m_apBuffers.GetArrayPtr(), sizeof(void*), dwNumBuffers, f);
|
||
|
}
|
||
|
|
||
|
void CAllocRecord::Subtract(CAllocRecord& Other)
|
||
|
{
|
||
|
m_dwTotalAlloc -= Other.m_dwTotalAlloc;
|
||
|
m_dwNumTimes -= Other.m_dwNumTimes;
|
||
|
for(int i = 0; i < m_apBuffers.Size(); i++)
|
||
|
{
|
||
|
for(int j = 0; j < Other.m_apBuffers.Size(); j++)
|
||
|
if(Other.m_apBuffers[j] == m_apBuffers[i])
|
||
|
break;
|
||
|
if(j < Other.m_apBuffers.Size())
|
||
|
{
|
||
|
m_apBuffers.RemoveAt(i);
|
||
|
i--;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CTls CStackContinuation::mtls_CurrentCont;
|
||
|
CStackContinuation* CStackContinuation::Set(CStackContinuation* pNew)
|
||
|
{
|
||
|
CStackContinuation* pPrev = (CStackContinuation*)(void*)mtls_CurrentCont;
|
||
|
mtls_CurrentCont = pNew;
|
||
|
if(pNew)
|
||
|
{
|
||
|
void* p;
|
||
|
__asm
|
||
|
{
|
||
|
mov eax, [ebp]
|
||
|
mov eax, [eax+4]
|
||
|
mov p, eax
|
||
|
}
|
||
|
pNew->m_pThisStackEnd = p;
|
||
|
}
|
||
|
return pPrev;
|
||
|
}
|
||
|
|
||
|
CStackContinuation* CStackContinuation::Get()
|
||
|
{
|
||
|
CStackContinuation* pPrev = (CStackContinuation*)(void*)mtls_CurrentCont;
|
||
|
return pPrev;
|
||
|
}
|