windows-nt/Source/XPSP1/NT/base/crts/crtw32/h/rtcpriv.h
2020-09-26 16:20:57 +08:00

540 lines
14 KiB
C++

/***
*rtcpriv.h - declarations and definitions for RTC use
*
* Copyright (c) 1985-2001, Microsoft Corporation. All rights reserved.
*
*Purpose:
* Contains the declarations and definitions for all RunTime Check
* support.
*
*Revision History:
* ??-??-?? KBF Created implementation header for RTC
* 05-26-99 KBF Removed RTCl & RTCv, added _RTC_ADVMEM stuff
* 10-14-99 PML Replace InitializeCriticalSection with wrapper function
* __crtInitCritSecAndSpinCount
*
****/
#ifndef _INC_RTCPRIV
#define _INC_RTCPRIV
#ifdef _RTC
#include <windows.h>
#include <winbase.h>
#include <malloc.h>
#include "rtcapi.h"
#pragma warning(disable:4710)
#pragma warning(disable:4711)
#ifndef __cplusplus
#error This header is only for use with the C++ compiler while building the RTC library code.
#endif
#ifdef _MSC_VER
#pragma pack(push, 4)
#endif /* _MSC_VER */
#ifndef _RTC_DEBUG
#pragma optimize("gb1", on)
#endif
// Multithreaded code locking stuff...
#define INIT_LOCK __crtInitCritSecAndSpinCount(&_RTC_memlock, _CRT_SPINCOUNT)
#define LOCK EnterCriticalSection(&_RTC_memlock)
#define UNLOCK LeaveCriticalSection(&_RTC_memlock)
#define DEL_LOCK DeleteCriticalSection(&_RTC_memlock)
#define TRY_LOCK TryEnterCriticalSection(&_RTC_memlock)
extern CRITICAL_SECTION _RTC_memlock;
// Typedefs
struct _RTC_globals;
#ifdef _RTC_ADVMEM
class _RTC_SimpleHeap;
class _RTC_Container;
class _RTC_HeapBlock;
class _RTC_BinaryTree;
template<class T> class HashTable;
typedef unsigned char shadowtag;
typedef unsigned char index_elem;
#endif
// General global functions & symbols
extern int _RTC_ErrorLevels[_RTC_ILLEGAL];
extern _RTC_globals *_RTC_globptr;
bool _RTC_Lock();
void _RTC_Unlock();
void _RTC_Failure(void *retaddr, int errnum);
_RTC_error_fn _RTC_GetErrorFunc(LPCVOID addr);
void _RTC_StackFailure(void *retaddr, const char *varname);
BOOL _RTC_GetSrcLine(DWORD address, char* source, int sourcelen,
int* pline, char** moduleName);
extern "C" {
void __fastcall _RTC_APISet(int on_off);
}
void _RTC_NotifyOthersOfChange(void *addr);
// When this changes, you'd better be sure that everything still works with the old stuff!
#define _RTC_CURRENT_VERSION 1
// The order of the initial stuff here can't change AT ALL!!!
struct _RTC_Funcs {
_RTC_error_fn err;
void (*notify)(void);
void *allocationBase;
_RTC_Funcs *next;
#ifdef _RTC_ADVMEM
int (*shadowoff)(void);
#endif
};
// definitions of library globals
// The order of this stuff MUST STAY THE SAME BETWEEN VERSION!!!
struct _RTC_globals {
int version;
CRITICAL_SECTION memlock;
_RTC_Funcs *callbacks;
#ifdef _RTC_ADVMEM
_RTC_SimpleHeap *heap2;
_RTC_SimpleHeap *heap4;
_RTC_SimpleHeap *heap8;
_RTC_Container *memhier;
shadowtag *shadow;
index_elem *pageidx;
HashTable<_RTC_HeapBlock> *heapblocks;
bool *pi_array;
bool shadowmemory;
#endif
};
#define _RTC_GLOBALS_SIZE 1024
/* Shadow Memory stuff */
#ifdef _RTC_ADVMEM
void _RTC_MS_Init();
void _RTC_MemFailure(void *retaddr, int errnum, const void *assign);
short _RTC_MSAllocShadow(memptr addr, unsigned size, unsigned state);
void _RTC_MSRestoreShadow(memptr addr, unsigned size, short id);
short _RTC_MSRenumberShadow(memptr addr, unsigned size, short notID);
void _RTC_MSFreeShadow(memptr addr, unsigned size);
void __cdecl _RTC_MSAllocateGlobals(void);
void _RTC_MSDecommitRange(memptr addr, unsigned size);
void _RTC_MSCommitRange(memptr addr, unsigned size, unsigned state);
extern "C" {
void __fastcall _RTC_CheckMem_API(memref addr, unsigned size);
}
// Unknown MUST be 0
#define IDX_STATE_UNKNOWN 0
#define IDX_STATE_ILLEGAL 1
#define IDX_STATE_PARTIALLY_KNOWN 2
#define IDX_STATE_FULLY_KNOWN 3
extern _RTC_Container *_RTC_memhier;
extern HashTable<_RTC_HeapBlock> *_RTC_heapblocks;
extern _RTC_SimpleHeap *_RTC_heap2;
extern _RTC_SimpleHeap *_RTC_heap4;
extern _RTC_SimpleHeap *_RTC_heap8;
extern shadowtag *_RTC_shadow;
extern index_elem *_RTC_pageidx;
extern bool *_RTC_pi_array;
extern bool _RTC_shadowmemory;
/**********************************/
#define ALLOC_SIZE 65536
class _RTC_SimpleHeap
{
struct FreeList
{
FreeList *next;
};
struct HeapNode
{
HeapNode *next; // next page in list (not necessarily free)
FreeList *free; // node-local free-list
union info
{
struct topStuff
{ // Stuff that pertains only to the top node
HeapNode *nxtFree; // Pointer to node containing free items
short wordSize; // The size of blocks in this heap
bool freePage; // True if there's a 100% free page
} top;
struct nonTopStuff
{ // Stuff that pertais only to non-top nodes
unsigned freeCount; // The free count for this node
HeapNode *prev; // previous link
} nontop;
} inf;
} head;
public:
_RTC_SimpleHeap(unsigned blockSize) throw();
~_RTC_SimpleHeap() throw();
void *operator new(unsigned) throw();
void operator delete(void *addr) throw();
void *alloc() throw();
void free(void *addr) throw();
};
extern _RTC_SimpleHeap *_RTC_heap2;
extern _RTC_SimpleHeap *_RTC_heap4;
extern _RTC_SimpleHeap *_RTC_heap8;
#define DATA(type, name) \
private: \
type _##name; \
public: \
type name() const { return _##name; }\
void name(type a) { _##name = a; }
class _RTC_HeapBlock
{
DATA(void *, addr); // The memory block address
DATA(unsigned, size); // The size of the block
DATA(_RTC_HeapBlock *, next); // The next element
DATA(_RTC_HeapBlock **,list); // The head list pointer
DATA(short, id); // The level ID of the block (for tiers)
DATA(short, tag); // The shadow tag of the block in shadow memory
public:
_RTC_HeapBlock(void *address, short lev)
: _addr(address), _id(lev) , _next(0), _list(0) {}
_RTC_HeapBlock(void *MemAddress, short Identifier, unsigned Size)
: _addr(MemAddress), _id(Identifier), _size(Size), _next(0), _list(0) {}
~_RTC_HeapBlock() throw()
{
if (_list) del(_list);
}
void *operator new(unsigned) throw()
{
return _RTC_heap8->alloc();
}
void operator delete(void *addr) throw()
{
_RTC_heap8->free(addr);
}
int operator<(const _RTC_HeapBlock &h) const
{
return _addr < h._addr;
}
int operator==(const _RTC_HeapBlock &h) const
{
return h._addr == _addr && h._id == _id;
}
bool contains(const _RTC_HeapBlock &h) const
{
return ((unsigned)_addr <= (unsigned)h._addr) &&
((unsigned)h._addr < (unsigned)_addr + _size);
}
unsigned hash(unsigned sz) const
{
return (((unsigned)_addr) ^ _id) % sz;
}
void add(_RTC_HeapBlock **lstHead) throw()
{
this->next(*lstHead);
this->list(lstHead);
*lstHead = this;
}
void del(_RTC_HeapBlock **lstHead) throw()
{
_RTC_HeapBlock *head = *lstHead;
_RTC_HeapBlock *prev = 0;
while (head != this)
{
prev = head;
head = head->next();
}
if (prev)
prev->next(this->next());
else
*lstHead = this->next();
next(0);
list(0);
}
};
#undef DATA
class _RTC_BinaryTree
{
public:
class BinaryNode
{
public:
BinaryNode *l, *r;
_RTC_Container *val;
void *operator new(unsigned) throw()
{
return _RTC_heap4->alloc();
}
void operator delete(void *addr) throw()
{
_RTC_heap4->free(addr);
}
BinaryNode(BinaryNode *L, BinaryNode *R, _RTC_Container *V)
: l(L), r(R), val(V) {}
void kill() throw();
};
private:
BinaryNode *tree;
public:
_RTC_BinaryTree(_RTC_Container *i) throw()
: tree(new BinaryNode(0, 0, i)) {}
~_RTC_BinaryTree() throw()
{
if (tree)
{
tree->kill();
delete tree;
}
}
void *operator new(unsigned) throw()
{
return _RTC_heap2->alloc();
}
void operator delete(void *addr) throw() { _RTC_heap2->free(addr); }
// This will return either the container or null
_RTC_Container *get(_RTC_HeapBlock *) throw();
// This just adds to the current sib list
_RTC_Container* add(_RTC_HeapBlock *) throw();
// This just removes the item from the current sib list
_RTC_Container *del(_RTC_HeapBlock *) throw();
// Here's an iterator
class iter
{
_RTC_Container **allSibs;
int curSib;
int totSibs;
friend class _RTC_BinaryTree;
public:
// This thing should never be allocated...
void *operator new(unsigned)
{
return 0;
}
};
_RTC_Container *FindFirst(iter *) throw();
_RTC_Container *FindNext(iter *) throw();
};
class _RTC_Container
{
// kids - the item that has all the children
_RTC_BinaryTree *kids;
// inf - the item that specifies containment
_RTC_HeapBlock *inf;
// This kills this container, and all contained info
void kill() throw();
public:
_RTC_Container(_RTC_HeapBlock *hb)
: inf(hb), kids(0) {}
~_RTC_Container() throw()
{
if (inf || kids)
kill();
}
_RTC_HeapBlock *info() const
{
return inf;
}
bool contains(const _RTC_HeapBlock *i) const throw()
{
return inf ? inf->contains(*i) : true;
}
// Returns the parent container
_RTC_Container *DelChild(_RTC_HeapBlock *i) throw();
// Add this item as a child inside this container
// It may or may not be a direct child
// It returns the parent container
_RTC_Container *AddChild(_RTC_HeapBlock *i) throw();
// Find the container that contains the data given
_RTC_Container *FindChild(_RTC_HeapBlock *i) throw();
typedef _RTC_HeapBlock data;
void *operator new(unsigned) throw() { return _RTC_heap2->alloc(); }
void operator delete(void *addr) throw() { _RTC_heap2->free(addr); }
};
template <class T>
class HashTable
{
unsigned size;
T **elems;
public:
HashTable(unsigned s, void *mem)
: elems((T**)mem), size(s)
{
memset(elems, 0, size * sizeof(T*));
}
~HashTable() {}
void *operator new(unsigned) throw()
{
return _RTC_heap2->alloc();
}
void operator delete(void *addr) throw()
{
_RTC_heap2->free(addr);
}
T *find(T *key) throw()
{
unsigned hkey = key->hash(size);
T *elem = elems[hkey];
while (elem && !(*elem == *key))
elem = elem->next();
return elem;
}
void add(T *itm) throw()
{
unsigned hkey = itm->hash(size);
itm->add(&elems[hkey]);
}
void del(T *key) throw()
{
unsigned hkey = key->hash(size);
T *elem = elems[hkey];
while (elem && !(*elem == *key))
elem = elem->next();
elem->del(&elems[hkey]);
}
};
#endif
// Stuff for the debugger exception mechanism
// Swiped fro vcexcept.h in the LangAPI
#if !defined(_vcexcept_h)
#define _vcexcept_h
// the facility code we have chosen is based on the fact that we already
// use an exception of 'msc' when we throw C++ exceptions
#define FACILITY_VISUALCPP ((LONG)0x6D)
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
/////////////////////////////////////////////////////////////////
// define all exceptions here, so we don't mess with each other
/////////////////////////////////////////////////////////////////
// used by CRTs for C++ exceptions, really defined in ehdata.h
//#define EH_EXCEPTION_NUMBER VcppException( 3<<30, 0x7363 ) // SEV_ERROR, used by CRTs for C++
// used by debugger to do e.g. SetThreadName call
#define EXCEPTION_VISUALCPP_DEBUGGER VcppException(1<<30, 5000) // SEV_INFORMATIONAL
#endif // _vcexcept_h
// Ping the VC debugger
#define HelloVC( exinfo ) \
RaiseException( EXCEPTION_VISUALCPP_DEBUGGER, 0, sizeof(exinfo)/sizeof(DWORD), (DWORD*)&exinfo )
enum EXCEPTION_DEBUGGER_ENUM
{
EXCEPTION_DEBUGGER_NAME_THREAD = 0x1000,
EXCEPTION_DEBUGGER_PROBE = 0x1001,
EXCEPTION_DEBUGGER_RUNTIMECHECK = 0x1002,
EXCEPTION_DEBUGGER_MAX = 0x1002 // largest value this debugger understands
};
// must be convertible to DWORDs for use by RaiseException
typedef struct tagEXCEPTION_VISUALCPP_DEBUG_INFO
{
DWORD dwType; // one of the enums from above
union
{
struct
{
LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use (eg User thread, System thread)
} SetName;
struct
{
DWORD dwLevelRequired; // 0 = do you understand this private exception, else max value of enum
PBYTE pbDebuggerPresent; // debugger puts a non-zero value in this address if there
} DebuggerProbe;
struct
{
DWORD dwRuntimeNumber; // the type of the runtime check
BOOL bRealBug; // TRUE if never a false-positive
PVOID pvReturnAddress; // caller puts a return address in here
PBYTE pbDebuggerPresent; // debugger puts a non-zero value in this address if handled it
LPCWSTR pwRuntimeMessage; // pointer to Unicode message (or NULL)
} RuntimeError;
};
} EXCEPTION_VISUALCPP_DEBUG_INFO;
#ifdef _MSC_VER
#pragma pack(pop)
#endif /* _MSC_VER */
#endif
#endif /* _INC_RTCPRIV */