1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
#include "stdafx.h"
#include "unwinder.h"
EXTERN_C void GetRuntimeStackWalkInfo(IN ULONG64 ControlPc,
OUT UINT_PTR* pModuleBase,
OUT UINT_PTR* pFuncEntry);
//---------------------------------------------------------------------------------------
//
// Given a control PC, return the base of the module it is in. For jitted managed code, this is the
// start of the code heap.
//
// Arguments:
// address - the specified address
// pdwBase - out parameter; returns the module base
//
// Return Value:
// S_OK if we retrieve the module base successfully;
// E_FAIL otherwise
//
HRESULT OOPStackUnwinder::GetModuleBase( DWORD64 address,
__out PDWORD64 pdwBase)
{
GetRuntimeStackWalkInfo(address, reinterpret_cast<UINT_PTR *>(pdwBase), NULL);
return ((*pdwBase == NULL) ? E_FAIL : S_OK);
}
//---------------------------------------------------------------------------------------
//
// Given a control PC, return the function entry of the functoin it is in.
//
// Arguments:
// address - the specified IP
// pBuffer - the buffer to store the retrieved function entry
// cbBuffer - the size of the buffer
//
// Return Value:
// S_OK if we retrieve the function entry successfully;
// E_INVALIDARG if the buffer is too small;
// E_FAIL otherwise
//
HRESULT OOPStackUnwinder::GetFunctionEntry( DWORD64 address,
__out_ecount(cbBuffer) PVOID pBuffer,
DWORD cbBuffer)
{
if (cbBuffer < sizeof(T_RUNTIME_FUNCTION))
{
return E_INVALIDARG;
}
PVOID pFuncEntry = NULL;
GetRuntimeStackWalkInfo(address, NULL, reinterpret_cast<UINT_PTR *>(&pFuncEntry));
if (pFuncEntry == NULL)
{
return E_FAIL;
}
memcpy(pBuffer, pFuncEntry, cbBuffer);
return S_OK;
}
|