Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1462 lines
33 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Insert this file into all projects using the memory system
  4. // It will cause that project to use the shader memory allocator
  5. //
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
  9. #undef PROTECTED_THINGS_ENABLE // allow use of _vsnprintf
  10. #if defined( _WIN32 ) && !defined( _X360 )
  11. #define WIN_32_LEAN_AND_MEAN
  12. #include <windows.h>
  13. #endif
  14. #ifdef _WIN32
  15. // ARG: crtdbg is necessary for certain definitions below,
  16. // but it also redefines malloc as a macro in release.
  17. // To disable this, we gotta define _DEBUG before including it.. BLEAH!
  18. #define _DEBUG 1
  19. #include "crtdbg.h"
  20. #ifdef NDEBUG
  21. #undef _DEBUG
  22. #endif
  23. // Turn this back off in release mode.
  24. #ifdef NDEBUG
  25. #undef _DEBUG
  26. #endif
  27. #endif
  28. #include "tier0/dbg.h"
  29. #include "tier0/memalloc.h"
  30. #include <string.h>
  31. #include <stdio.h>
  32. #include "memdbgoff.h"
  33. #if POSIX
  34. #define __cdecl
  35. #endif
  36. #if defined( _WIN32 ) && !defined( _X360 )
  37. const char *MakeModuleFileName()
  38. {
  39. if ( g_pMemAlloc && g_pMemAlloc->IsDebugHeap() )
  40. {
  41. char *pszModuleName = (char *)HeapAlloc( GetProcessHeap(), 0, MAX_PATH ); // small leak, debug only
  42. MEMORY_BASIC_INFORMATION mbi;
  43. static int dummy;
  44. VirtualQuery( &dummy, &mbi, sizeof(mbi) );
  45. GetModuleFileName( reinterpret_cast<HMODULE>(mbi.AllocationBase), pszModuleName, MAX_PATH );
  46. char *pDot = strrchr( pszModuleName, '.' );
  47. if ( pDot )
  48. {
  49. char *pSlash = strrchr( pszModuleName, '\\' );
  50. if ( pSlash )
  51. {
  52. pszModuleName = pSlash + 1;
  53. *pDot = 0;
  54. }
  55. }
  56. return pszModuleName;
  57. }
  58. return NULL;
  59. }
  60. //-----------------------------------------------------------------------------
  61. // Purpose: helper class to detect when static construction has been done by the CRT
  62. //-----------------------------------------------------------------------------
  63. class CStaticConstructionCheck
  64. {
  65. public:
  66. volatile bool m_bConstructed = true;
  67. };
  68. static CStaticConstructionCheck s_CheckStaticsConstructed;
  69. const char *GetModuleFileName()
  70. {
  71. #if !defined(_MSC_VER) || ( _MSC_VER >= 1900 ) // VC 2015 and above, with the UCRT, will crash if you use a static before it is constructed
  72. if ( !s_CheckStaticsConstructed.m_bConstructed )
  73. return nullptr;
  74. #endif
  75. static const char *pszOwner = MakeModuleFileName();
  76. return pszOwner;
  77. }
  78. static void *AllocUnattributed( size_t nSize )
  79. {
  80. const char *pszOwner = GetModuleFileName();
  81. if ( !pszOwner )
  82. return g_pMemAlloc->Alloc(nSize);
  83. else
  84. return g_pMemAlloc->Alloc(nSize, pszOwner, 0);
  85. }
  86. static void *ReallocUnattributed( void *pMem, size_t nSize )
  87. {
  88. const char *pszOwner = GetModuleFileName();
  89. if ( !pszOwner )
  90. return g_pMemAlloc->Realloc(pMem, nSize);
  91. else
  92. return g_pMemAlloc->Realloc(pMem, nSize, pszOwner, 0);
  93. }
  94. #else
  95. #define MakeModuleFileName() NULL
  96. inline void *AllocUnattributed( size_t nSize )
  97. {
  98. return g_pMemAlloc->Alloc(nSize);
  99. }
  100. inline void *ReallocUnattributed( void *pMem, size_t nSize )
  101. {
  102. return g_pMemAlloc->Realloc(pMem, nSize);
  103. }
  104. #endif
  105. //-----------------------------------------------------------------------------
  106. // Standard functions in the CRT that we're going to override to call our allocator
  107. //-----------------------------------------------------------------------------
  108. #if defined(_WIN32) && !defined(_STATIC_LINKED)
  109. // this magic only works under win32
  110. // under linux this malloc() overrides the libc malloc() and so we
  111. // end up in a recursion (as g_pMemAlloc->Alloc() calls malloc)
  112. #if _MSC_VER >= 1900
  113. #define SUPPRESS_INVALID_PARAMETER_NO_INFO
  114. #define ALLOC_CALL __declspec(restrict)
  115. #define FREE_CALL
  116. #elif _MSC_VER >= 1400
  117. #define ALLOC_CALL _CRTNOALIAS _CRTRESTRICT
  118. #define FREE_CALL _CRTNOALIAS
  119. #else
  120. #define ALLOC_CALL
  121. #define FREE_CALL
  122. #endif
  123. extern "C"
  124. {
  125. ALLOC_CALL void *malloc( size_t nSize )
  126. {
  127. return AllocUnattributed( nSize );
  128. }
  129. FREE_CALL void free( void *pMem )
  130. {
  131. g_pMemAlloc->Free(pMem);
  132. }
  133. ALLOC_CALL void *realloc( void *pMem, size_t nSize )
  134. {
  135. return ReallocUnattributed( pMem, nSize );
  136. }
  137. ALLOC_CALL void *calloc( size_t nCount, size_t nElementSize )
  138. {
  139. void *pMem = AllocUnattributed( nElementSize * nCount );
  140. memset(pMem, 0, nElementSize * nCount);
  141. return pMem;
  142. }
  143. } // end extern "C"
  144. //-----------------------------------------------------------------------------
  145. // Non-standard MSVC functions that we're going to override to call our allocator
  146. //-----------------------------------------------------------------------------
  147. extern "C"
  148. {
  149. // 64-bit
  150. #ifdef _WIN64
  151. void* __cdecl _malloc_base( size_t nSize )
  152. {
  153. return AllocUnattributed( nSize );
  154. }
  155. #else
  156. ALLOC_CALL void *_malloc_base( size_t nSize )
  157. {
  158. return AllocUnattributed( nSize );
  159. }
  160. #endif
  161. ALLOC_CALL void *_calloc_base( size_t nCount, size_t nSize )
  162. {
  163. void *pMem = AllocUnattributed( nSize*nCount );
  164. memset(pMem, 0, nSize*nCount );
  165. return pMem;
  166. }
  167. ALLOC_CALL void *_realloc_base( void *pMem, size_t nSize )
  168. {
  169. return ReallocUnattributed( pMem, nSize );
  170. }
  171. ALLOC_CALL void *_recalloc_base( void *pMem, size_t nSize )
  172. {
  173. void *pMemOut = ReallocUnattributed( pMem, nSize );
  174. if ( !pMem )
  175. {
  176. memset( pMemOut, 0, nSize );
  177. }
  178. return pMemOut;
  179. }
  180. void _free_base( void *pMem )
  181. {
  182. g_pMemAlloc->Free(pMem);
  183. }
  184. void *__cdecl _expand_base( void *pMem, size_t nNewSize, int nBlockUse )
  185. {
  186. Assert( 0 );
  187. return NULL;
  188. }
  189. // crt
  190. void * __cdecl _malloc_crt(size_t size)
  191. {
  192. return AllocUnattributed( size );
  193. }
  194. void * __cdecl _calloc_crt(size_t count, size_t size)
  195. {
  196. return _calloc_base( count, size );
  197. }
  198. void * __cdecl _realloc_crt(void *ptr, size_t size)
  199. {
  200. return _realloc_base( ptr, size );
  201. }
  202. void * __cdecl _recalloc_crt(void *ptr, size_t count, size_t size)
  203. {
  204. return _recalloc_base( ptr, size * count );
  205. }
  206. ALLOC_CALL void * __cdecl _recalloc ( void * memblock, size_t count, size_t size )
  207. {
  208. void *pMem = ReallocUnattributed( memblock, size * count );
  209. if ( !memblock )
  210. {
  211. memset( pMem, 0, size * count );
  212. }
  213. return pMem;
  214. }
  215. size_t _msize_base( void *pMem )
  216. {
  217. return g_pMemAlloc->GetSize(pMem);
  218. }
  219. size_t _msize( void *pMem )
  220. {
  221. return _msize_base(pMem);
  222. }
  223. size_t msize( void *pMem )
  224. {
  225. return g_pMemAlloc->GetSize(pMem);
  226. }
  227. void *__cdecl _heap_alloc( size_t nSize )
  228. {
  229. return AllocUnattributed( nSize );
  230. }
  231. void *__cdecl _nh_malloc( size_t nSize, int )
  232. {
  233. return AllocUnattributed( nSize );
  234. }
  235. void *__cdecl _expand( void *pMem, size_t nSize )
  236. {
  237. Assert( 0 );
  238. return NULL;
  239. }
  240. unsigned int _amblksiz = 16; //BYTES_PER_PARA;
  241. #if _MSC_VER >= 1400
  242. HANDLE _crtheap = (HANDLE)1; // PatM Can't be 0 or CRT pukes
  243. int __active_heap = 1;
  244. #endif // _MSC_VER >= 1400
  245. size_t __cdecl _get_sbh_threshold( void )
  246. {
  247. return 0;
  248. }
  249. int __cdecl _set_sbh_threshold( size_t )
  250. {
  251. return 0;
  252. }
  253. int _heapchk()
  254. {
  255. return g_pMemAlloc->heapchk();
  256. }
  257. int _heapmin()
  258. {
  259. return 1;
  260. }
  261. int __cdecl _heapadd( void *, size_t )
  262. {
  263. return 0;
  264. }
  265. int __cdecl _heapset( unsigned int )
  266. {
  267. return 0;
  268. }
  269. size_t __cdecl _heapused( size_t *, size_t * )
  270. {
  271. return 0;
  272. }
  273. #ifdef _WIN32
  274. int __cdecl _heapwalk( _HEAPINFO * )
  275. {
  276. return 0;
  277. }
  278. #endif
  279. } // end extern "C"
  280. //-----------------------------------------------------------------------------
  281. // Debugging functions that we're going to override to call our allocator
  282. // NOTE: These have to be here for release + debug builds in case we
  283. // link to a debug static lib!!!
  284. //-----------------------------------------------------------------------------
  285. extern "C"
  286. {
  287. void *malloc_db( size_t nSize, const char *pFileName, int nLine )
  288. {
  289. return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
  290. }
  291. void free_db( void *pMem, const char *pFileName, int nLine )
  292. {
  293. g_pMemAlloc->Free(pMem, pFileName, nLine);
  294. }
  295. void *realloc_db( void *pMem, size_t nSize, const char *pFileName, int nLine )
  296. {
  297. return g_pMemAlloc->Realloc(pMem, nSize, pFileName, nLine);
  298. }
  299. } // end extern "C"
  300. //-----------------------------------------------------------------------------
  301. // These methods are standard MSVC heap initialization + shutdown methods
  302. //-----------------------------------------------------------------------------
  303. extern "C"
  304. {
  305. #if !defined( _X360 )
  306. int __cdecl _heap_init()
  307. {
  308. return g_pMemAlloc != NULL;
  309. }
  310. void __cdecl _heap_term()
  311. {
  312. }
  313. #endif
  314. }
  315. #endif
  316. //-----------------------------------------------------------------------------
  317. // Prevents us from using an inappropriate new or delete method,
  318. // ensures they are here even when linking against debug or release static libs
  319. //-----------------------------------------------------------------------------
  320. #ifndef NO_MEMOVERRIDE_NEW_DELETE
  321. #ifdef OSX
  322. void *__cdecl operator new( size_t nSize ) throw (std::bad_alloc)
  323. #else
  324. void *__cdecl operator new( size_t nSize )
  325. #endif
  326. {
  327. return AllocUnattributed( nSize );
  328. }
  329. void *__cdecl operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
  330. {
  331. return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
  332. }
  333. #ifdef OSX
  334. void __cdecl operator delete( void *pMem ) throw()
  335. #else
  336. void __cdecl operator delete( void *pMem )
  337. #endif
  338. {
  339. g_pMemAlloc->Free( pMem );
  340. }
  341. #ifdef OSX
  342. void operator delete(void*pMem, std::size_t)
  343. #else
  344. void operator delete(void*pMem, std::size_t) throw()
  345. #endif
  346. {
  347. g_pMemAlloc->Free( pMem );
  348. }
  349. #ifdef OSX
  350. void *__cdecl operator new[]( size_t nSize ) throw (std::bad_alloc)
  351. #else
  352. void *__cdecl operator new[]( size_t nSize )
  353. #endif
  354. {
  355. return AllocUnattributed( nSize );
  356. }
  357. void *__cdecl operator new[] ( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
  358. {
  359. return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
  360. }
  361. #ifdef OSX
  362. void __cdecl operator delete[]( void *pMem ) throw()
  363. #else
  364. void __cdecl operator delete[]( void *pMem )
  365. #endif
  366. {
  367. g_pMemAlloc->Free( pMem );
  368. }
  369. #endif
  370. //-----------------------------------------------------------------------------
  371. // Override some debugging allocation methods in MSVC
  372. // NOTE: These have to be here for release + debug builds in case we
  373. // link to a debug static lib!!!
  374. //-----------------------------------------------------------------------------
  375. #ifndef _STATIC_LINKED
  376. #ifdef _WIN32
  377. // This here just hides the internal file names, etc of allocations
  378. // made in the c runtime library
  379. #define CRT_INTERNAL_FILE_NAME "C-runtime internal"
  380. class CAttibCRT
  381. {
  382. public:
  383. CAttibCRT(int nBlockUse) : m_nBlockUse(nBlockUse)
  384. {
  385. if (m_nBlockUse == _CRT_BLOCK)
  386. {
  387. g_pMemAlloc->PushAllocDbgInfo(CRT_INTERNAL_FILE_NAME, 0);
  388. }
  389. }
  390. ~CAttibCRT()
  391. {
  392. if (m_nBlockUse == _CRT_BLOCK)
  393. {
  394. g_pMemAlloc->PopAllocDbgInfo();
  395. }
  396. }
  397. private:
  398. int m_nBlockUse;
  399. };
  400. #define AttribIfCrt() CAttibCRT _attrib(nBlockUse)
  401. #elif defined(POSIX)
  402. #define AttribIfCrt()
  403. #endif // _WIN32
  404. extern "C"
  405. {
  406. void *__cdecl _nh_malloc_dbg( size_t nSize, int nFlag, int nBlockUse,
  407. const char *pFileName, int nLine )
  408. {
  409. AttribIfCrt();
  410. return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
  411. }
  412. void *__cdecl _malloc_dbg( size_t nSize, int nBlockUse,
  413. const char *pFileName, int nLine )
  414. {
  415. AttribIfCrt();
  416. return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
  417. }
  418. #if defined( _X360 )
  419. void *__cdecl _calloc_dbg_impl( size_t nNum, size_t nSize, int nBlockUse,
  420. const char * szFileName, int nLine, int * errno_tmp )
  421. {
  422. return _calloc_dbg( nNum, nSize, nBlockUse, szFileName, nLine );
  423. }
  424. #endif
  425. void *__cdecl _calloc_dbg( size_t nNum, size_t nSize, int nBlockUse,
  426. const char *pFileName, int nLine )
  427. {
  428. AttribIfCrt();
  429. void *pMem = g_pMemAlloc->Alloc(nSize * nNum, pFileName, nLine);
  430. memset(pMem, 0, nSize * nNum);
  431. return pMem;
  432. }
  433. void *__cdecl _calloc_dbg_impl( size_t nNum, size_t nSize, int nBlockUse,
  434. const char * szFileName, int nLine, int * errno_tmp )
  435. {
  436. return _calloc_dbg( nNum, nSize, nBlockUse, szFileName, nLine );
  437. }
  438. void *__cdecl _realloc_dbg( void *pMem, size_t nNewSize, int nBlockUse,
  439. const char *pFileName, int nLine )
  440. {
  441. AttribIfCrt();
  442. return g_pMemAlloc->Realloc(pMem, nNewSize, pFileName, nLine);
  443. }
  444. void *__cdecl _expand_dbg( void *pMem, size_t nNewSize, int nBlockUse,
  445. const char *pFileName, int nLine )
  446. {
  447. Assert( 0 );
  448. return NULL;
  449. }
  450. void __cdecl _free_dbg( void *pMem, int nBlockUse )
  451. {
  452. AttribIfCrt();
  453. g_pMemAlloc->Free(pMem);
  454. }
  455. size_t __cdecl _msize_dbg( void *pMem, int nBlockUse )
  456. {
  457. #ifdef _WIN32
  458. return _msize(pMem);
  459. #elif POSIX
  460. Assert( "_msize_dbg unsupported" );
  461. return 0;
  462. #endif
  463. }
  464. #ifdef _WIN32
  465. #if defined(_DEBUG) && _MSC_VER >= 1300
  466. // aligned base
  467. ALLOC_CALL void *__cdecl _aligned_malloc_base( size_t size, size_t align )
  468. {
  469. return MemAlloc_AllocAligned( size, align );
  470. }
  471. inline void *MemAlloc_Unalign( void *pMemBlock )
  472. {
  473. unsigned *pAlloc = (unsigned *)pMemBlock;
  474. // pAlloc points to the pointer to starting of the memory block
  475. pAlloc = (unsigned *)(((size_t)pAlloc & ~(sizeof( void * ) - 1)) - sizeof( void * ));
  476. // pAlloc is the pointer to the start of memory block
  477. return *((unsigned **)pAlloc);
  478. }
  479. ALLOC_CALL void *__cdecl _aligned_realloc_base( void *ptr, size_t size, size_t align )
  480. {
  481. if ( ptr && !size )
  482. {
  483. MemAlloc_FreeAligned( ptr );
  484. return NULL;
  485. }
  486. void *pNew = MemAlloc_AllocAligned( size, align );
  487. if ( ptr )
  488. {
  489. void *ptrUnaligned = MemAlloc_Unalign( ptr );
  490. size_t oldSize = g_pMemAlloc->GetSize( ptrUnaligned );
  491. size_t oldOffset = (uintp)ptr - (uintp)ptrUnaligned;
  492. size_t copySize = oldSize - oldOffset;
  493. if ( copySize > size )
  494. copySize = size;
  495. memcpy( pNew, ptr, copySize );
  496. MemAlloc_FreeAligned( ptr );
  497. }
  498. return pNew;
  499. }
  500. ALLOC_CALL void *__cdecl _aligned_recalloc_base( void *ptr, size_t size, size_t align )
  501. {
  502. Error( "Unsupported function\n" );
  503. return NULL;
  504. }
  505. FREE_CALL void __cdecl _aligned_free_base( void *ptr )
  506. {
  507. MemAlloc_FreeAligned( ptr );
  508. }
  509. // aligned
  510. ALLOC_CALL void * __cdecl _aligned_malloc( size_t size, size_t align )
  511. {
  512. return _aligned_malloc_base(size, align);
  513. }
  514. ALLOC_CALL void *__cdecl _aligned_realloc(void *memblock, size_t size, size_t align)
  515. {
  516. return _aligned_realloc_base(memblock, size, align);
  517. }
  518. ALLOC_CALL void * __cdecl _aligned_recalloc( void * memblock, size_t count, size_t size, size_t align )
  519. {
  520. return _aligned_recalloc_base(memblock, count * size, align);
  521. }
  522. FREE_CALL void __cdecl _aligned_free( void *memblock )
  523. {
  524. _aligned_free_base(memblock);
  525. }
  526. // aligned offset base
  527. ALLOC_CALL void * __cdecl _aligned_offset_malloc_base( size_t size, size_t align, size_t offset )
  528. {
  529. Assert( IsPC() || 0 );
  530. return NULL;
  531. }
  532. ALLOC_CALL void * __cdecl _aligned_offset_realloc_base( void * memblock, size_t size, size_t align, size_t offset)
  533. {
  534. Assert( IsPC() || 0 );
  535. return NULL;
  536. }
  537. ALLOC_CALL void * __cdecl _aligned_offset_recalloc_base( void * memblock, size_t size, size_t align, size_t offset)
  538. {
  539. Assert( IsPC() || 0 );
  540. return NULL;
  541. }
  542. // aligned offset
  543. ALLOC_CALL void *__cdecl _aligned_offset_malloc(size_t size, size_t align, size_t offset)
  544. {
  545. return _aligned_offset_malloc_base( size, align, offset );
  546. }
  547. ALLOC_CALL void *__cdecl _aligned_offset_realloc(void *memblock, size_t size, size_t align, size_t offset)
  548. {
  549. return _aligned_offset_realloc_base( memblock, size, align, offset );
  550. }
  551. ALLOC_CALL void * __cdecl _aligned_offset_recalloc( void * memblock, size_t count, size_t size, size_t align, size_t offset )
  552. {
  553. return _aligned_offset_recalloc_base( memblock, count * size, align, offset );
  554. }
  555. #endif // _MSC_VER >= 1400
  556. #endif
  557. } // end extern "C"
  558. //-----------------------------------------------------------------------------
  559. // Override some the _CRT debugging allocation methods in MSVC
  560. //-----------------------------------------------------------------------------
  561. #ifdef _WIN32
  562. extern "C"
  563. {
  564. int _CrtDumpMemoryLeaks(void)
  565. {
  566. return 0;
  567. }
  568. _CRT_DUMP_CLIENT _CrtSetDumpClient( _CRT_DUMP_CLIENT dumpClient )
  569. {
  570. return NULL;
  571. }
  572. int _CrtSetDbgFlag( int nNewFlag )
  573. {
  574. return g_pMemAlloc->CrtSetDbgFlag( nNewFlag );
  575. }
  576. // 64-bit port.
  577. #define AFNAME(var) __p_##var
  578. #define AFRET(var) &var
  579. #if defined(_crtDbgFlag)
  580. #undef _crtDbgFlag
  581. #endif
  582. #if defined(_crtBreakAlloc)
  583. #undef _crtBreakAlloc
  584. #endif
  585. int _crtDbgFlag = _CRTDBG_ALLOC_MEM_DF;
  586. int* AFNAME(_crtDbgFlag)(void)
  587. {
  588. return AFRET(_crtDbgFlag);
  589. }
  590. long _crtBreakAlloc; /* Break on this allocation */
  591. long* AFNAME(_crtBreakAlloc) (void)
  592. {
  593. return AFRET(_crtBreakAlloc);
  594. }
  595. void __cdecl _CrtSetDbgBlockType( void *pMem, int nBlockUse )
  596. {
  597. DebuggerBreak();
  598. }
  599. _CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook( _CRT_ALLOC_HOOK pfnNewHook )
  600. {
  601. DebuggerBreak();
  602. return NULL;
  603. }
  604. long __cdecl _CrtSetBreakAlloc( long lNewBreakAlloc )
  605. {
  606. return g_pMemAlloc->CrtSetBreakAlloc( lNewBreakAlloc );
  607. }
  608. int __cdecl _CrtIsValidHeapPointer( const void *pMem )
  609. {
  610. return g_pMemAlloc->CrtIsValidHeapPointer( pMem );
  611. }
  612. int __cdecl _CrtIsValidPointer( const void *pMem, unsigned int size, int access )
  613. {
  614. return g_pMemAlloc->CrtIsValidPointer( pMem, size, access );
  615. }
  616. int __cdecl _CrtCheckMemory( void )
  617. {
  618. // FIXME: Remove this when we re-implement the heap
  619. return g_pMemAlloc->CrtCheckMemory( );
  620. }
  621. int __cdecl _CrtIsMemoryBlock( const void *pMem, unsigned int nSize,
  622. long *plRequestNumber, char **ppFileName, int *pnLine )
  623. {
  624. DebuggerBreak();
  625. return 1;
  626. }
  627. int __cdecl _CrtMemDifference( _CrtMemState *pState, const _CrtMemState * oldState, const _CrtMemState * newState )
  628. {
  629. DebuggerBreak();
  630. return FALSE;
  631. }
  632. void __cdecl _CrtMemDumpStatistics( const _CrtMemState *pState )
  633. {
  634. DebuggerBreak();
  635. }
  636. void __cdecl _CrtMemCheckpoint( _CrtMemState *pState )
  637. {
  638. // FIXME: Remove this when we re-implement the heap
  639. g_pMemAlloc->CrtMemCheckpoint( pState );
  640. }
  641. void __cdecl _CrtMemDumpAllObjectsSince( const _CrtMemState *pState )
  642. {
  643. DebuggerBreak();
  644. }
  645. void __cdecl _CrtDoForAllClientObjects( void (*pfn)(void *, void *), void * pContext )
  646. {
  647. DebuggerBreak();
  648. }
  649. //-----------------------------------------------------------------------------
  650. // Methods in dbgrpt.cpp
  651. //-----------------------------------------------------------------------------
  652. long _crtAssertBusy = -1;
  653. int __cdecl _CrtSetReportMode( int nReportType, int nReportMode )
  654. {
  655. return g_pMemAlloc->CrtSetReportMode( nReportType, nReportMode );
  656. }
  657. _HFILE __cdecl _CrtSetReportFile( int nRptType, _HFILE hFile )
  658. {
  659. return (_HFILE)g_pMemAlloc->CrtSetReportFile( nRptType, hFile );
  660. }
  661. _CRT_REPORT_HOOK __cdecl _CrtSetReportHook( _CRT_REPORT_HOOK pfnNewHook )
  662. {
  663. return (_CRT_REPORT_HOOK)g_pMemAlloc->CrtSetReportHook( pfnNewHook );
  664. }
  665. int __cdecl _CrtDbgReport( int nRptType, const char * szFile,
  666. int nLine, const char * szModule, const char * szFormat, ... )
  667. {
  668. static char output[1024];
  669. va_list args;
  670. if ( szFormat )
  671. {
  672. va_start( args, szFormat );
  673. _vsnprintf( output, sizeof( output )-1, szFormat, args );
  674. va_end( args );
  675. }
  676. else
  677. {
  678. output[0] = 0;
  679. }
  680. return g_pMemAlloc->CrtDbgReport( nRptType, szFile, nLine, szModule, output );
  681. }
  682. #if _MSC_VER >= 1400
  683. // Configure VS so that it will record crash dumps on pure-call violations
  684. // and invalid parameter handlers.
  685. // If you manage to call a pure-virtual function (easily done if you indirectly
  686. // call a pure-virtual function from the base-class constructor or destructor)
  687. // or if you invoke the invalid parameter handler (printf(NULL); is one way)
  688. // then no crash dump will be created.
  689. // This crash redirects the handlers for these two events so that crash dumps
  690. // are created.
  691. //
  692. // The ErrorHandlerRegistrar object must be in memoverride.cpp so that it will
  693. // be placed in every DLL and EXE. This is required because each DLL and EXE
  694. // gets its own copy of the C run-time and these overrides are set on a per-CRT
  695. // basis.
  696. /*
  697. // This sample code will cause pure-call and invalid_parameter violations and
  698. // was used for testing:
  699. class Base
  700. {
  701. public:
  702. virtual void PureFunction() = 0;
  703. Base()
  704. {
  705. NonPureFunction();
  706. }
  707. void NonPureFunction()
  708. {
  709. PureFunction();
  710. }
  711. };
  712. class Derived : public Base
  713. {
  714. public:
  715. void PureFunction() OVERRIDE
  716. {
  717. }
  718. };
  719. void PureCallViolation()
  720. {
  721. Derived derived;
  722. }
  723. void InvalidParameterViolation()
  724. {
  725. printf( NULL );
  726. }
  727. */
  728. #include <stdlib.h>
  729. #include "minidump.h"
  730. // Disable compiler optimizations. If we don't do this then VC++ generates code
  731. // that confuses the Visual Studio debugger and causes it to display completely
  732. // random call stacks. That makes the minidumps excruciatingly hard to understand.
  733. #pragma optimize("", off)
  734. // Write a minidump file, unless running under the debugger in which case break
  735. // into the debugger.
  736. // The "int dummy" parameter is so that the callers can be unique so that the
  737. // linker won't use its /opt:icf optimization to collapse them together. This
  738. // makes reading the call stack easier.
  739. void __cdecl WriteMiniDumpOrBreak( int dummy, const char *pchName )
  740. {
  741. if ( Plat_IsInDebugSession() )
  742. {
  743. __debugbreak();
  744. // Continue at your peril...
  745. }
  746. else
  747. {
  748. WriteMiniDump( pchName );
  749. // Call Plat_ExitProcess so we don't continue in a bad state.
  750. TerminateProcess(GetCurrentProcess(), 0);
  751. }
  752. }
  753. void __cdecl VPureCall()
  754. {
  755. WriteMiniDumpOrBreak( 0, "PureClass" );
  756. }
  757. void VInvalidParameterHandler(const wchar_t* expression,
  758. const wchar_t* function,
  759. const wchar_t* file,
  760. unsigned int line,
  761. uintptr_t pReserved)
  762. {
  763. WriteMiniDumpOrBreak( 1, "InvalidParameterHandler" );
  764. }
  765. // Restore compiler optimizations.
  766. #pragma optimize("", on)
  767. // Helper class for registering error callbacks. See above for details.
  768. class ErrorHandlerRegistrar
  769. {
  770. public:
  771. ErrorHandlerRegistrar();
  772. } s_ErrorHandlerRegistration;
  773. ErrorHandlerRegistrar::ErrorHandlerRegistrar()
  774. {
  775. _set_purecall_handler( VPureCall );
  776. _set_invalid_parameter_handler( VInvalidParameterHandler );
  777. }
  778. #if defined( _DEBUG )
  779. // wrapper which passes no debug info; not available in debug
  780. #ifndef SUPPRESS_INVALID_PARAMETER_NO_INFO
  781. void __cdecl _invalid_parameter_noinfo(void)
  782. {
  783. Assert(0);
  784. }
  785. #endif
  786. #endif /* defined( _DEBUG ) */
  787. #if defined( _DEBUG ) || defined( USE_MEM_DEBUG )
  788. int __cdecl __crtMessageWindowW( int nRptType, const wchar_t * szFile, const wchar_t * szLine,
  789. const wchar_t * szModule, const wchar_t * szUserMessage )
  790. {
  791. Assert(0);
  792. return 0;
  793. }
  794. int __cdecl _CrtDbgReportV( int nRptType, const wchar_t *szFile, int nLine,
  795. const wchar_t *szModule, const wchar_t *szFormat, va_list arglist )
  796. {
  797. Assert(0);
  798. return 0;
  799. }
  800. int __cdecl _CrtDbgReportW( int nRptType, const wchar_t *szFile, int nLine,
  801. const wchar_t *szModule, const wchar_t *szFormat, ...)
  802. {
  803. Assert(0);
  804. return 0;
  805. }
  806. #if _MSC_VER >= 1900
  807. int __cdecl _VCrtDbgReportA( int nRptType, void* ReturnAddress, const char * szFile, int nLine,
  808. const char * szModule, const char * szFormat, va_list arglist )
  809. {
  810. Assert(0);
  811. return 0;
  812. }
  813. #else
  814. int __cdecl _VCrtDbgReportA( int nRptType, const wchar_t * szFile, int nLine,
  815. const wchar_t * szModule, const wchar_t * szFormat, va_list arglist )
  816. {
  817. Assert( 0 );
  818. return 0;
  819. }
  820. #endif
  821. int __cdecl _CrtSetReportHook2( int mode, _CRT_REPORT_HOOK pfnNewHook )
  822. {
  823. _CrtSetReportHook( pfnNewHook );
  824. return 0;
  825. }
  826. #endif /* defined( _DEBUG ) || defined( USE_MEM_DEBUG ) */
  827. extern "C" int __crtDebugCheckCount = FALSE;
  828. extern "C" int __cdecl _CrtSetCheckCount( int fCheckCount )
  829. {
  830. int oldCheckCount = __crtDebugCheckCount;
  831. return oldCheckCount;
  832. }
  833. extern "C" int __cdecl _CrtGetCheckCount( void )
  834. {
  835. return __crtDebugCheckCount;
  836. }
  837. // aligned offset debug
  838. extern "C" void * __cdecl _aligned_offset_recalloc_dbg( void * memblock, size_t count, size_t size, size_t align, size_t offset, const char * f_name, int line_n )
  839. {
  840. Assert( IsPC() || 0 );
  841. void *pMem = ReallocUnattributed( memblock, size * count );
  842. if ( !memblock )
  843. {
  844. memset( pMem, 0, size * count );
  845. }
  846. return pMem;
  847. }
  848. extern "C" void * __cdecl _aligned_recalloc_dbg( void *memblock, size_t count, size_t size, size_t align, const char * f_name, int line_n )
  849. {
  850. return _aligned_offset_recalloc_dbg(memblock, count, size, align, 0, f_name, line_n);
  851. }
  852. extern "C" void * __cdecl _recalloc_dbg ( void * memblock, size_t count, size_t size, int nBlockUse, const char * szFileName, int nLine )
  853. {
  854. return _aligned_offset_recalloc_dbg(memblock, count, size, 0, 0, szFileName, nLine);
  855. }
  856. _CRT_REPORT_HOOK __cdecl _CrtGetReportHook( void )
  857. {
  858. return NULL;
  859. }
  860. #endif
  861. int __cdecl _CrtReportBlockType(const void * pUserData)
  862. {
  863. return 0;
  864. }
  865. } // end extern "C"
  866. #endif // _WIN32
  867. // Most files include this file, so when it's used it adds an extra .ValveDbg section,
  868. // to help identify debug binaries.
  869. #ifdef _WIN32
  870. #ifndef NDEBUG // _DEBUG
  871. #pragma data_seg("ValveDBG")
  872. volatile const char* DBG = "*** DEBUG STUB ***";
  873. #endif
  874. #endif
  875. #endif
  876. // Extras added prevent dbgheap.obj from being included - DAL
  877. #ifdef _WIN32
  878. extern "C"
  879. {
  880. size_t __crtDebugFillThreshold = 0;
  881. extern "C" void * __cdecl _heap_alloc_base (size_t size) {
  882. assert(0);
  883. return NULL;
  884. }
  885. void * __cdecl _heap_alloc_dbg( size_t nSize, int nBlockUse, const char * szFileName, int nLine)
  886. {
  887. return _heap_alloc(nSize);
  888. }
  889. // 64-bit
  890. #ifdef _WIN64
  891. static void * __cdecl realloc_help( void * pUserData, size_t * pnNewSize, int nBlockUse,const char * szFileName,
  892. int nLine, int fRealloc )
  893. {
  894. assert(0); // Shouldn't be needed
  895. return NULL;
  896. }
  897. #else
  898. static void * __cdecl realloc_help( void * pUserData, size_t nNewSize, int nBlockUse, const char * szFileName,
  899. int nLine, int fRealloc)
  900. {
  901. assert(0); // Shouldn't be needed
  902. return NULL;
  903. }
  904. #endif
  905. void __cdecl _free_nolock( void * pUserData)
  906. {
  907. // I don't think the second param is used in memoverride
  908. _free_dbg(pUserData, 0);
  909. }
  910. void __cdecl _free_dbg_nolock( void * pUserData, int nBlockUse)
  911. {
  912. _free_dbg(pUserData, 0);
  913. }
  914. _CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook ( void)
  915. {
  916. assert(0);
  917. return NULL;
  918. }
  919. static int __cdecl CheckBytes( unsigned char * pb, unsigned char bCheck, size_t nSize)
  920. {
  921. int bOkay = TRUE;
  922. return bOkay;
  923. }
  924. _CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient ( void)
  925. {
  926. assert(0);
  927. return NULL;
  928. }
  929. #if _MSC_VER >= 1400
  930. static void __cdecl _printMemBlockData( _locale_t plocinfo, _CrtMemBlockHeader * pHead)
  931. {
  932. }
  933. static void __cdecl _CrtMemDumpAllObjectsSince_stat( const _CrtMemState * state, _locale_t plocinfo)
  934. {
  935. }
  936. #endif
  937. void * __cdecl _aligned_malloc_dbg( size_t size, size_t align, const char * f_name, int line_n)
  938. {
  939. return _aligned_malloc(size, align);
  940. }
  941. void * __cdecl _aligned_realloc_dbg( void *memblock, size_t size, size_t align,
  942. const char * f_name, int line_n)
  943. {
  944. return _aligned_realloc(memblock, size, align);
  945. }
  946. void * __cdecl _aligned_offset_malloc_dbg( size_t size, size_t align, size_t offset,
  947. const char * f_name, int line_n)
  948. {
  949. return _aligned_offset_malloc(size, align, offset);
  950. }
  951. void * __cdecl _aligned_offset_realloc_dbg( void * memblock, size_t size, size_t align,
  952. size_t offset, const char * f_name, int line_n)
  953. {
  954. return _aligned_offset_realloc(memblock, size, align, offset);
  955. }
  956. void __cdecl _aligned_free_dbg( void * memblock)
  957. {
  958. _aligned_free(memblock);
  959. }
  960. #if _MSC_VER < 1900
  961. size_t __cdecl _CrtSetDebugFillThreshold( size_t _NewDebugFillThreshold)
  962. {
  963. assert(0);
  964. return 0;
  965. }
  966. //===========================================
  967. // NEW!!! 64-bit
  968. char * __cdecl _strdup ( const char * string )
  969. {
  970. int nSize = (int)strlen(string) + 1;
  971. // Check for integer underflow.
  972. if ( nSize <= 0 )
  973. return NULL;
  974. char *pCopy = (char*)AllocUnattributed( nSize );
  975. if ( pCopy )
  976. memcpy( pCopy, string, nSize );
  977. return pCopy;
  978. }
  979. #endif
  980. #if 0
  981. _TSCHAR * __cdecl _tfullpath_dbg ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen, int nBlockUse, const char * szFileName, int nLine )
  982. {
  983. Assert(0);
  984. return NULL;
  985. }
  986. _TSCHAR * __cdecl _tfullpath ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen )
  987. {
  988. Assert(0);
  989. return NULL;
  990. }
  991. _TSCHAR * __cdecl _tgetdcwd_lk_dbg ( int drive, _TSCHAR *pnbuf, int maxlen, int nBlockUse, const char * szFileName, int nLine )
  992. {
  993. Assert(0);
  994. return NULL;
  995. }
  996. _TSCHAR * __cdecl _tgetdcwd_nolock ( int drive, _TSCHAR *pnbuf, int maxlen )
  997. {
  998. Assert(0);
  999. return NULL;
  1000. }
  1001. errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname, int nBlockUse, const char * szFileName, int nLine )
  1002. {
  1003. Assert(0);
  1004. return 0;
  1005. }
  1006. errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname )
  1007. {
  1008. Assert(0);
  1009. return 0;
  1010. }
  1011. _TSCHAR * __cdecl _ttempnam_dbg ( const _TSCHAR *dir, const _TSCHAR *pfx, int nBlockUse, const char * szFileName, int nLine )
  1012. {
  1013. Assert(0);
  1014. return 0;
  1015. }
  1016. _TSCHAR * __cdecl _ttempnam ( const _TSCHAR *dir, const _TSCHAR *pfx )
  1017. {
  1018. Assert(0);
  1019. return 0;
  1020. }
  1021. wchar_t * __cdecl _wcsdup_dbg ( const wchar_t * string, int nBlockUse, const char * szFileName, int nLine )
  1022. {
  1023. Assert(0);
  1024. return 0;
  1025. }
  1026. wchar_t * __cdecl _wcsdup ( const wchar_t * string )
  1027. {
  1028. Assert(0);
  1029. return 0;
  1030. }
  1031. #endif
  1032. } // end extern "C"
  1033. #if _MSC_VER >= 1400
  1034. //-----------------------------------------------------------------------------
  1035. // XBox Memory Allocator Override
  1036. //-----------------------------------------------------------------------------
  1037. #if defined( _X360 )
  1038. #if defined( _DEBUG ) || defined( USE_MEM_DEBUG )
  1039. #include "utlmap.h"
  1040. MEMALLOC_DEFINE_EXTERNAL_TRACKING( XMem );
  1041. CThreadFastMutex g_XMemAllocMutex;
  1042. void XMemAlloc_RegisterAllocation( void *p, DWORD dwAllocAttributes )
  1043. {
  1044. if ( !g_pMemAlloc )
  1045. {
  1046. // core xallocs cannot be journaled until system is ready
  1047. return;
  1048. }
  1049. AUTO_LOCK_FM( g_XMemAllocMutex );
  1050. int size = XMemSize( p, dwAllocAttributes );
  1051. MemAlloc_RegisterExternalAllocation( XMem, p, size );
  1052. }
  1053. void XMemAlloc_RegisterDeallocation( void *p, DWORD dwAllocAttributes )
  1054. {
  1055. if ( !g_pMemAlloc )
  1056. {
  1057. // core xallocs cannot be journaled until system is ready
  1058. return;
  1059. }
  1060. AUTO_LOCK_FM( g_XMemAllocMutex );
  1061. int size = XMemSize( p, dwAllocAttributes );
  1062. MemAlloc_RegisterExternalDeallocation( XMem, p, size );
  1063. }
  1064. #else
  1065. #define XMemAlloc_RegisterAllocation( p, a ) ((void)0)
  1066. #define XMemAlloc_RegisterDeallocation( p, a ) ((void)0)
  1067. #endif
  1068. //-----------------------------------------------------------------------------
  1069. // XMemAlloc
  1070. //
  1071. // XBox Memory Allocator Override
  1072. //-----------------------------------------------------------------------------
  1073. LPVOID WINAPI XMemAlloc( SIZE_T dwSize, DWORD dwAllocAttributes )
  1074. {
  1075. LPVOID ptr;
  1076. XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes;
  1077. bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL );
  1078. if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI )
  1079. {
  1080. MEM_ALLOC_CREDIT();
  1081. switch ( pAttribs->dwAlignment )
  1082. {
  1083. case XALLOC_ALIGNMENT_4:
  1084. ptr = g_pMemAlloc->Alloc( dwSize );
  1085. break;
  1086. case XALLOC_ALIGNMENT_8:
  1087. ptr = MemAlloc_AllocAligned( dwSize, 8 );
  1088. break;
  1089. case XALLOC_ALIGNMENT_DEFAULT:
  1090. case XALLOC_ALIGNMENT_16:
  1091. default:
  1092. ptr = MemAlloc_AllocAligned( dwSize, 16 );
  1093. break;
  1094. }
  1095. if ( pAttribs->dwZeroInitialize != 0 )
  1096. {
  1097. memset( ptr, 0, XMemSize( ptr, dwAllocAttributes ) );
  1098. }
  1099. return ptr;
  1100. }
  1101. ptr = XMemAllocDefault( dwSize, dwAllocAttributes );
  1102. if ( ptr )
  1103. {
  1104. XMemAlloc_RegisterAllocation( ptr, dwAllocAttributes );
  1105. }
  1106. return ptr;
  1107. }
  1108. //-----------------------------------------------------------------------------
  1109. // XMemFree
  1110. //
  1111. // XBox Memory Allocator Override
  1112. //-----------------------------------------------------------------------------
  1113. VOID WINAPI XMemFree( PVOID pAddress, DWORD dwAllocAttributes )
  1114. {
  1115. if ( !pAddress )
  1116. {
  1117. return;
  1118. }
  1119. XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes;
  1120. bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL );
  1121. if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI )
  1122. {
  1123. switch ( pAttribs->dwAlignment )
  1124. {
  1125. case XALLOC_ALIGNMENT_4:
  1126. return g_pMemAlloc->Free( pAddress );
  1127. default:
  1128. return MemAlloc_FreeAligned( pAddress );
  1129. }
  1130. return;
  1131. }
  1132. XMemAlloc_RegisterDeallocation( pAddress, dwAllocAttributes );
  1133. XMemFreeDefault( pAddress, dwAllocAttributes );
  1134. }
  1135. //-----------------------------------------------------------------------------
  1136. // XMemSize
  1137. //
  1138. // XBox Memory Allocator Override
  1139. //-----------------------------------------------------------------------------
  1140. SIZE_T WINAPI XMemSize( PVOID pAddress, DWORD dwAllocAttributes )
  1141. {
  1142. XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes;
  1143. bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL );
  1144. if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI )
  1145. {
  1146. switch ( pAttribs->dwAlignment )
  1147. {
  1148. case XALLOC_ALIGNMENT_4:
  1149. return g_pMemAlloc->GetSize( pAddress );
  1150. default:
  1151. return MemAlloc_GetSizeAligned( pAddress );
  1152. }
  1153. }
  1154. return XMemSizeDefault( pAddress, dwAllocAttributes );
  1155. }
  1156. #endif
  1157. #pragma warning(push)
  1158. #pragma warning(disable: 4483)
  1159. #if _MSC_FULL_VER >= 140050415
  1160. #define _NATIVE_STARTUP_NAMESPACE __identifier("<CrtImplementationDetails>")
  1161. #else /* _MSC_FULL_VER >= 140050415 */
  1162. #define _NATIVE_STARTUP_NAMESPACE __CrtImplementationDetails
  1163. #endif /* _MSC_FULL_VER >= 140050415 */
  1164. namespace _NATIVE_STARTUP_NAMESPACE
  1165. {
  1166. class NativeDll
  1167. {
  1168. private:
  1169. static const unsigned int ProcessDetach = 0;
  1170. static const unsigned int ProcessAttach = 1;
  1171. static const unsigned int ThreadAttach = 2;
  1172. static const unsigned int ThreadDetach = 3;
  1173. static const unsigned int ProcessVerifier = 4;
  1174. public:
  1175. inline static bool IsInDllMain()
  1176. {
  1177. return false;
  1178. }
  1179. inline static bool IsInProcessAttach()
  1180. {
  1181. return false;
  1182. }
  1183. inline static bool IsInProcessDetach()
  1184. {
  1185. return false;
  1186. }
  1187. inline static bool IsInVcclrit()
  1188. {
  1189. return false;
  1190. }
  1191. inline static bool IsSafeForManagedCode()
  1192. {
  1193. if (!IsInDllMain())
  1194. {
  1195. return true;
  1196. }
  1197. if (IsInVcclrit())
  1198. {
  1199. return true;
  1200. }
  1201. return !IsInProcessAttach() && !IsInProcessDetach();
  1202. }
  1203. };
  1204. }
  1205. #pragma warning(pop)
  1206. #endif // _MSC_VER >= 1400
  1207. #endif // !STEAM && !NO_MALLOC_OVERRIDE
  1208. #endif // _WIN32