/*** *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 #include #include #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 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 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 */