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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
// 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 "forward_declarations.h"
#ifdef FEATURE_RWX_MEMORY
#define WRITE_ACCESS_HOLDER_ARG , rh::util::WriteAccessHolder *pRWAccessHolder
#define WRITE_ACCESS_HOLDER_ARG_NULL_DEFAULT , rh::util::WriteAccessHolder *pRWAccessHolder = NULL
#define PASS_WRITE_ACCESS_HOLDER_ARG , pRWAccessHolder
#else // FEATURE_RWX_MEMORY
#define WRITE_ACCESS_HOLDER_ARG
#define WRITE_ACCESS_HOLDER_ARG_NULL_DEFAULT
#define PASS_WRITE_ACCESS_HOLDER_ARG
#endif // FEATURE_RWX_MEMORY
class AllocHeap
{
public:
AllocHeap();
#ifdef FEATURE_RWX_MEMORY
// If pAccessMgr is non-NULL, it will be used to manage R/W access to the memory allocated.
AllocHeap(UInt32 rwProtectType = PAGE_READWRITE,
UInt32 roProtectType = 0, // 0 indicates "same as rwProtectType"
rh::util::MemAccessMgr* pAccessMgr = NULL);
#endif // FEATURE_RWX_MEMORY
bool Init();
bool Init(UInt8 * pbInitialMem,
UIntNative cbInitialMemCommit,
UIntNative cbInitialMemReserve,
bool fShouldFreeInitialMem);
~AllocHeap();
// If AllocHeap was created with a MemAccessMgr, pRWAccessHolder must be non-NULL.
// On return, the holder will permit R/W access to the allocated memory until it
// is destructed.
UInt8 * Alloc(UIntNative cbMem WRITE_ACCESS_HOLDER_ARG_NULL_DEFAULT);
// If AllocHeap was created with a MemAccessMgr, pRWAccessHolder must be non-NULL.
// On return, the holder will permit R/W access to the allocated memory until it
// is destructed.
UInt8 * AllocAligned(UIntNative cbMem,
UIntNative alignment
WRITE_ACCESS_HOLDER_ARG_NULL_DEFAULT);
// Returns true if this AllocHeap owns the memory range [pvMem, pvMem+cbMem)
bool Contains(void * pvMem,
UIntNative cbMem);
#ifdef FEATURE_RWX_MEMORY
// Used with previously-allocated memory for which RW access is needed again.
// Returns true on success. R/W access will be granted until the holder is
// destructed.
bool AcquireWriteAccess(void* pvMem,
UIntNative cbMem,
rh::util::WriteAccessHolder* pHolder);
#endif // FEATURE_RWX_MEMORY
private:
// Allocation Helpers
UInt8* _Alloc(UIntNative cbMem, UIntNative alignment WRITE_ACCESS_HOLDER_ARG);
bool _AllocNewBlock(UIntNative cbMem);
UInt8* _AllocFromCurBlock(UIntNative cbMem, UIntNative alignment WRITE_ACCESS_HOLDER_ARG);
bool _CommitFromCurBlock(UIntNative cbMem);
// Access protection helpers
#ifdef FEATURE_RWX_MEMORY
bool _AcquireWriteAccess(UInt8* pvMem, UIntNative cbMem, rh::util::WriteAccessHolder* pHolder);
#endif // FEATURE_RWX_MEMORY
bool _UpdateMemPtrs(UInt8* pNextFree, UInt8* pFreeCommitEnd, UInt8* pFreeReserveEnd);
bool _UpdateMemPtrs(UInt8* pNextFree, UInt8* pFreeCommitEnd);
bool _UpdateMemPtrs(UInt8* pNextFree);
bool _UseAccessManager() { return m_rwProtectType != m_roProtectType; }
static const UIntNative s_minBlockSize = OS_PAGE_SIZE;
typedef rh::util::MemRange Block;
typedef DPTR(Block) PTR_Block;
struct BlockListElem : public Block
{
BlockListElem(Block const & block)
: Block(block)
{}
BlockListElem(UInt8 * pbMem, UIntNative cbMem)
: Block(pbMem, cbMem)
{}
Block m_block;
PTR_Block m_pNext;
};
typedef SList<BlockListElem> BlockList;
BlockList m_blockList;
UInt32 m_rwProtectType; // READ/WRITE/EXECUTE/etc
UInt32 m_roProtectType; // What to do with fully allocated and initialized pages.
#ifdef FEATURE_RWX_MEMORY
rh::util::MemAccessMgr* m_pAccessMgr;
rh::util::WriteAccessHolder m_hCurPageRW; // Used to hold RW access to the current allocation page
// Passed as pHint to MemAccessMgr::AcquireWriteAccess.
#endif // FEATURE_RWX_MEMORY
UInt8 * m_pNextFree;
UInt8 * m_pFreeCommitEnd;
UInt8 * m_pFreeReserveEnd;
UInt8 * m_pbInitialMem;
bool m_fShouldFreeInitialMem;
Crst m_lock;
INDEBUG(bool m_fIsInit;)
};
typedef DPTR(AllocHeap) PTR_AllocHeap;
//-------------------------------------------------------------------------------------------------
void * __cdecl operator new(size_t n, AllocHeap * alloc);
void * __cdecl operator new[](size_t n, AllocHeap * alloc);
|