diff --git a/inc/malloc_km.h b/kext/kmalloc.h similarity index 100% rename from inc/malloc_km.h rename to kext/kmalloc.h diff --git a/inc/new_km.h b/kext/knew.h similarity index 100% rename from inc/new_km.h rename to kext/knew.h diff --git a/msvc/ucxxrt.vcxproj b/msvc/ucxxrt.vcxproj index d9fad6a..f611493 100644 --- a/msvc/ucxxrt.vcxproj +++ b/msvc/ucxxrt.vcxproj @@ -270,7 +270,6 @@ - @@ -299,7 +298,6 @@ - @@ -343,26 +341,16 @@ - - - - true - true - true - true - + - - + - - + - diff --git a/msvc/ucxxrt.vcxproj.filters b/msvc/ucxxrt.vcxproj.filters index 084f3ee..79dfd79 100644 --- a/msvc/ucxxrt.vcxproj.filters +++ b/msvc/ucxxrt.vcxproj.filters @@ -254,9 +254,6 @@ ucxxrt\crt\vcruntime - - ucxxrt\crt\vcruntime - ucxxrt\crt\vcruntime @@ -338,9 +335,6 @@ ucxxrt\crt\vcruntime - - ucxxrt\crt\vcruntime - ucxxrt\crt\vcruntime @@ -647,33 +641,18 @@ ucxxrt\ucrt\heap - - ucxxrt\ucrt\heap - - - ucxxrt\ucrt\heap - ucxxrt\ucrt\heap ucxxrt\ucrt\heap - - ucxxrt\ucrt\heap - - - ucxxrt\ucrt\heap - ucxxrt\ucrt\heap ucxxrt\ucrt\heap - - ucxxrt\ucrt\heap - ucxxrt\ucrt\heap @@ -686,13 +665,13 @@ ucxxrt\crt\vcruntime - + ucxxrt\ucrt\heap - + ucxxrt\ucrt\heap - + ucxxrt\ucrt\heap diff --git a/src/crt/vcruntime/delete_debug.cpp b/src/crt/vcruntime/delete_debug.cpp deleted file mode 100644 index 8a2326f..0000000 --- a/src/crt/vcruntime/delete_debug.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// delete_debug.cpp -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Defines the debug operator delete (both scalar and array forms). -// -#include -#include - - - -#ifdef _DEBUG - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void __CRTDECL operator delete( - void* block, - int const block_use, - char const* file_name, - int const line_number - ) noexcept - { - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - _free_dbg(block, block_use); - } - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void __CRTDECL operator delete[]( - void* block, - int const block_use, - char const* file_name, - int const line_number - ) noexcept - { - return operator delete(block, block_use, file_name, line_number); - } - -#else // ^^^ _DEBUG ^^^ // vvv !_DEBUG vvv // - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void __CRTDECL operator delete( - void* block, - int const block_use, - char const* file_name, - int const line_number - ) noexcept - { - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return operator delete(block); - } - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void __CRTDECL operator delete[]( - void* block, - int const block_use, - char const* file_name, - int const line_number - ) noexcept - { - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return operator delete[](block); - } - -#endif diff --git a/src/crt/vcruntime/delete_km.cpp b/src/crt/vcruntime/delete_km.cpp index 8bf344b..4bf2f9d 100644 --- a/src/crt/vcruntime/delete_km.cpp +++ b/src/crt/vcruntime/delete_km.cpp @@ -14,6 +14,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////// // delete() Fallback Ordering diff --git a/src/crt/vcruntime/delete_scalar.cpp b/src/crt/vcruntime/delete_scalar.cpp index 85e7cf3..3ba19e0 100644 --- a/src/crt/vcruntime/delete_scalar.cpp +++ b/src/crt/vcruntime/delete_scalar.cpp @@ -30,9 +30,5 @@ _CRT_SECURITYCRITICAL_ATTRIBUTE void __CRTDECL operator delete(void* const block) noexcept { - #ifdef _DEBUG - _free_dbg(block, _UNKNOWN_BLOCK); - #else free(block); - #endif } diff --git a/src/crt/vcruntime/internal_shared.h b/src/crt/vcruntime/internal_shared.h index c06de47..6bb07e4 100644 --- a/src/crt/vcruntime/internal_shared.h +++ b/src/crt/vcruntime/internal_shared.h @@ -248,53 +248,17 @@ extern "C++" // CRT Memory Allocation and Management // //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -#ifdef _DEBUG - // These must match the definitions in the CoreCRT's debug header. They - // are defined separately here to avoid unwanted CRT header dependencies. - #define _NORMAL_BLOCK 1 - #define _CRT_BLOCK 2 - - #define _calloc_crt(c, s) (_calloc_dbg ( c, s, _CRT_BLOCK, __FILE__, __LINE__)) - #define _free_crt(p) (_free_dbg (p, _CRT_BLOCK )) - #define _malloc_crt(s) (_malloc_dbg ( s, _CRT_BLOCK, __FILE__, __LINE__)) - #define _msize_crt(p) (_msize_dbg (p, _CRT_BLOCK )) - #define _recalloc_crt(p, c, s) (_recalloc_dbg(p, c, s, _CRT_BLOCK, __FILE__, __LINE__)) - #define _realloc_crt(p, s) (_realloc_dbg (p, s, _CRT_BLOCK, __FILE__, __LINE__)) - - #define _malloca_crt(size) \ - __pragma(warning(suppress: 6255)) \ - (_MallocaComputeSize(size) != 0 \ - ? _MarkAllocaS(_malloc_crt(_MallocaComputeSize(size)), _ALLOCA_S_HEAP_MARKER) \ - : NULL) +// When building for vcruntime*.dll, we are not a part of the UCRT or OS so we +// should use the public allocation functions exported by the UCRT. +#define _calloc_crt calloc +#define _free_crt free +#define _malloc_crt malloc +#define _realloc_crt realloc +#define _msize_crt _msize +#define _recalloc_crt _recalloc -#else // ^^^ _DEBUG ^^^ // vvv !_DEBUG vvv - - // The *_crt macros call the allocation function that vcruntime should use for - // internal allocations. It changes based off of where it is being built. - - #ifdef _CRT_WINDOWS - // When building for the UCRT, we want to use the internal allocation functions. - // We need to ensure that users hooking the public allocation functions do not - // interfere with the UCRT's allocations. - #define _calloc_crt _calloc_base - #define _free_crt _free_base - #define _malloc_crt _malloc_base - #define _realloc_crt _realloc_base - #define _msize_crt _msize_base - #define _recalloc_crt _recalloc_base - #else - // When building for vcruntime*.dll, we are not a part of the UCRT or OS so we - // should use the public allocation functions exported by the UCRT. - #define _calloc_crt calloc - #define _free_crt free - #define _malloc_crt malloc - #define _realloc_crt realloc - #define _msize_crt _msize - #define _recalloc_crt _recalloc - #endif - - #define _malloca_crt(size) \ +#define _malloca_crt(size) \ __pragma(warning(suppress: 6255)) \ (_MallocaComputeSize(size) != 0 \ ? ((_MallocaComputeSize(size) <= _ALLOCA_S_THRESHOLD) \ @@ -302,8 +266,6 @@ extern "C++" : _MarkAllocaS(_malloc_crt(_MallocaComputeSize(size)), _ALLOCA_S_HEAP_MARKER)) \ : NULL) -#endif // !_DEBUG - #pragma warning(push) #pragma warning(disable: 6014) __inline void __CRTDECL _freea_crt(_Pre_maybenull_ _Post_invalid_ void* memory) @@ -482,7 +444,6 @@ extern "C++" { #define _malloca_crt_t(t, n) (__crt_scoped_stack_ptr_tag(static_cast(_malloca_crt ( (n) * sizeof(t))))) - enum : int { __crt_maximum_pointer_shift = sizeof(uintptr_t) * 8 @@ -650,22 +611,6 @@ extern "C++" { -#define _CRT_DEBUGGER_IGNORE -1 -#define _CRT_DEBUGGER_GSFAILURE 1 -#define _CRT_DEBUGGER_INVALIDPARAMETER 2 -#define _CRT_DEBUGGER_ABORT 3 - -// Note: These names are well-known to the debugger -#ifdef _M_IX86 - void __cdecl _crt_debugger_hook(int); - #define _CRT_DEBUGGER_HOOK _crt_debugger_hook -#else - void __cdecl __crt_debugger_hook(int); - #define _CRT_DEBUGGER_HOOK __crt_debugger_hook -#endif - - - //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // // Precondition Validation Macros diff --git a/src/crt/vcruntime/new_debug.cpp b/src/crt/vcruntime/new_debug.cpp deleted file mode 100644 index 42576c5..0000000 --- a/src/crt/vcruntime/new_debug.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// new_debug.cpp -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Defines the debug operator new (both scalar and array forms). -// -// The debug operator new and operator new[] are implemented in both the debug -// and retail CRT libraries. In the retail CRT, they simply call the ordinary -// operator new. These operators are only declared in the public header files -// when building with the debug CRT. Implementing these operators in the CRT -// libraries makes it easier to override them by linking to nothrownew.obj. -// -#include -#include -#include -#include -#include - - - -#ifdef _DEBUG - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void* __CRTDECL operator new( - size_t const size, - int const block_use, - char const* file_name, - int const line_number - ) - { - for (;;) - { - if (void* const block = _malloc_dbg(size, block_use, file_name, line_number)) - { - return block; - } - - if (_callnewh(size) == 0) - { - if (size == SIZE_MAX) - { - __scrt_throw_std_bad_array_new_length(); - } - else - { - __scrt_throw_std_bad_alloc(); - } - } - } - } - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void* __CRTDECL operator new[]( - size_t const size, - int const block_use, - char const* file_name, - int const line_number - ) - { - return operator new(size, block_use, file_name, line_number); - } - -#else // ^^^ _DEBUG ^^^ // vvv !_DEBUG vvv // - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void* __CRTDECL operator new( - size_t const size, - int const block_use, - char const* file_name, - int const line_number - ) - { - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return operator new(size); - } - - _CRT_SECURITYCRITICAL_ATTRIBUTE - void* __CRTDECL operator new[]( - size_t const size, - int const block_use, - char const* file_name, - int const line_number - ) - { - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return operator new[](size); - } - -#endif // !_DEBUG diff --git a/src/crt/vcruntime/new_km.cpp b/src/crt/vcruntime/new_km.cpp index 50b0423..6849844 100644 --- a/src/crt/vcruntime/new_km.cpp +++ b/src/crt/vcruntime/new_km.cpp @@ -13,6 +13,7 @@ #include #include #include +#include // Enable the compiler to elide null checks during LTCG #pragma comment(linker, "/ThrowingNew") diff --git a/src/crt/vcruntime/std_type_info.cpp b/src/crt/vcruntime/std_type_info.cpp index 724ec97..2051fa7 100644 --- a/src/crt/vcruntime/std_type_info.cpp +++ b/src/crt/vcruntime/std_type_info.cpp @@ -81,8 +81,8 @@ extern "C" char const* __cdecl __std_type_info_name( nullptr, data->_DecoratedName + 1, 0, - [](size_t const n) { return _malloc_crt(n); }, - [](void* const p) { return _free_crt(p); }, + [](size_t const n) { return malloc(n); }, + [](void* const p) { return free(p); }, UNDNAME_32_BIT_DECODE | UNDNAME_TYPE_ONLY)); if (!undecorated_name) @@ -100,7 +100,7 @@ extern "C" char const* __cdecl __std_type_info_name( size_t const undecorated_name_count = undecorated_name_length + 1; size_t const node_size = sizeof(SLIST_ENTRY) + undecorated_name_count; - __crt_unique_heap_ptr node_block(_malloc_crt(node_size)); + __crt_unique_heap_ptr node_block(malloc(node_size)); if (!node_block) { return nullptr; // CRT_REFACTOR TODO This is nonconforming @@ -143,7 +143,7 @@ extern "C" void __cdecl __std_type_info_destroy_list( while (current_node) { PSLIST_ENTRY const next_node = current_node->Next; - _free_crt(current_node); + free(current_node); current_node = next_node; } } diff --git a/src/ucrt/heap/align.cpp b/src/ucrt/heap/align.cpp index 5f71c49..121f7fa 100644 --- a/src/ucrt/heap/align.cpp +++ b/src/ucrt/heap/align.cpp @@ -37,121 +37,88 @@ * *******************************************************************************/ -extern "C" void __cdecl _aligned_free_base( - _Pre_maybenull_ _Post_invalid_ void* block - ); - -_Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_malloc_base( - _In_ size_t size, - _In_ size_t alignment - ); - -_Check_return_ -extern "C" size_t __cdecl _aligned_msize_base( - _Pre_notnull_ void* block, - _In_ size_t alignment, - _In_ size_t offset - ); - -_Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_offset_malloc_base( - _In_ size_t size, - _In_ size_t alignment, - _In_ size_t offset - ); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_offset_realloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t size, - _In_ size_t alignment, - _In_ size_t offset - ); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size * count) -extern "C" void* __cdecl _aligned_offset_recalloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t count, - _In_ size_t size, - _In_ size_t alignment, - _In_ size_t offset - ); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_realloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t size, - _In_ size_t alignment - ); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size * count) -extern "C" void* __cdecl _aligned_recalloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t count, - _In_ size_t size, - _In_ size_t alignment - ); +extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_malloc( + size_t const size, + size_t const alignment, + size_t const offset +); -/*** -* void *_aligned_malloc_base(size_t size, size_t alignment) -* - Get a block of aligned memory from the heap. -* -* Purpose: -* Allocate of block of aligned memory aligned on the alignment of at least -* size bytes from the heap and return a pointer to it. -* -* Entry: -* size_t size - size of block requested -* size_t alignment - alignment of memory (needs to be a power of 2) -* -* Exit: -* Success: Pointer to memory block -* Failure: Null, errno is set -* -* Exceptions: -* Input parameters are validated. Refer to the validation section of the function. -* -*******************************************************************************/ +// These functions are patchable and therefore must be marked noinline. +// Their *_base implementations are marked __forceinline in order to +// ensure each export is separated from each other and that there is +// enough space in each export to host a patch. -extern "C" void* __cdecl _aligned_malloc_base( +extern "C" __declspec(noinline) void __cdecl _aligned_free(void* const block) +{ + uintptr_t ptr; + + if (block == nullptr) + return; + + ptr = (uintptr_t)block; + + /* ptr points to the pointer to starting of the memory block */ + ptr = (ptr & ~(PTR_SZ - 1)) - PTR_SZ; + + /* ptr is the pointer to the start of memory block*/ + ptr = *((uintptr_t*)ptr); + free((void*)ptr); +} + +extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_malloc( size_t const size, size_t const alignment ) { - return _aligned_offset_malloc_base(size, alignment, 0); + return _aligned_offset_malloc(size, alignment, 0); } -/*** -* void *_aligned_offset_malloc_base(size_t size, size_t alignment, int offset) -* - Get a block of memory from the heap. -* -* Purpose: -* Allocate a block of memory which is shifted by offset from alignment of -* at least size bytes from the heap and return a pointer to it. -* -* Entry: -* size_t size - size of block of memory -* size_t alignment - alignment of memory (needs to be a power of 2) -* size_t offset - offset of memory from the alignment -* -* Exit: -* Success: Pointer to memory block -* Failure: Null, errno is set -* -* Exceptions: -* Input parameters are validated. Refer to the validation section of the function. -* -*******************************************************************************/ +extern "C" __declspec(noinline) size_t __cdecl _aligned_msize( + void* const block, + size_t const alignment, + size_t const offset) +{ + size_t align = alignment; + size_t header_size = 0; /* Size of the header block */ + size_t footer_size = 0; /* Size of the footer block */ + size_t total_size = 0; /* total size of the allocated block */ + size_t user_size = 0; /* size of the user block*/ + uintptr_t gap = 0; /* keep the alignment of the data block */ + /* after the sizeof(void*) aligned pointer */ + /* to the beginning of the allocated block */ + uintptr_t ptr = 0; /* computes the beginning of the allocated block */ + + _VALIDATE_RETURN(block != nullptr, EINVAL, static_cast(-1)); + + /* HEADER SIZE + FOOTER SIZE = GAP + ALIGN + SIZE OF A POINTER*/ + /* HEADER SIZE + USER SIZE + FOOTER SIZE = TOTAL SIZE */ + + ptr = (uintptr_t)block; /* ptr points to the start of the aligned memory block */ + ptr = (ptr & ~(PTR_SZ - 1)) - PTR_SZ; /* ptr is one position behind memblock */ + /* the value in ptr is the start of the real allocated block */ + ptr = *((uintptr_t *)ptr); /* after dereference ptr points to the beginning of the allocated block */ -extern "C" void* __cdecl _aligned_offset_malloc_base( - size_t size, - size_t align, - size_t offset + total_size = _msize((void*)ptr); + header_size = (uintptr_t) block - ptr; + gap = (0 - offset) & (PTR_SZ - 1); + + /* Alignment cannot be less than sizeof(void*) */ + align = (align > PTR_SZ ? align : PTR_SZ) -1; + footer_size = gap + align + PTR_SZ - header_size; + user_size = total_size - header_size - footer_size; + + return user_size; +} + +extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_malloc( + size_t const size, + size_t const alignment, + size_t const offset ) { uintptr_t ptr, retptr, gap; size_t nonuser_size,block_size; + size_t align = alignment; /* validation section */ _VALIDATE_RETURN(IS_2_POW_N(align), EINVAL, nullptr); @@ -175,130 +142,26 @@ extern "C" void* __cdecl _aligned_offset_malloc_base( return (void *)retptr; } -/*** -* -* void *_aligned_realloc_base(void * memblock, size_t size, size_t alignment) -* - Reallocate a block of aligned memory from the heap. -* -* Purpose: -* Reallocates of block of aligned memory aligned on the alignment of at -* least size bytes from the heap and return a pointer to it. Size can be -* either greater or less than the original size of the block. -* The reallocation may result in moving the block as well as changing the -* size. -* -* Entry: -* void *memblock - pointer to block in the heap previously allocated by -* call to _aligned_malloc(), _aligned_offset_malloc(), -* _aligned_realloc() or _aligned_offset_realloc(). -* size_t size - size of block requested -* size_t alignment - alignment of memory -* -* Exit: -* Success: Pointer to re-allocated memory block -* Failure: Null, errno is set -* -* Exceptions: -* Input parameters are validated. Refer to the validation section of the function. -* -*******************************************************************************/ - -extern "C" void* __cdecl _aligned_realloc_base( - void* const block, - size_t const size, - size_t const alignment - ) -{ - return _aligned_offset_realloc_base(block, size, alignment, 0); -} - -/*** -* -* void *_aligned_recalloc_base(void * memblock, size_t count, size_t size, size_t alignment) -* - Reallocate a block of aligned memory from the heap. -* -* Purpose: -* Reallocates of block of aligned memory aligned on the alignment of at -* least size bytes from the heap and return a pointer to it. Size can be -* either greater or less than the original size of the block. -* The reallocation may result in moving the block as well as changing the -* size. -* -* Entry: -* void *memblock - pointer to block in the heap previously allocated by -* call to _aligned_malloc(), _aligned_offset_malloc(), -* _aligned_realloc() or _aligned_offset_realloc(). -* size_t count - count of items -* size_t size - size of item -* size_t alignment - alignment of memory -* -* Exit: -* Success: Pointer to re-allocated memory block -* Failure: Null, errno is set -* -* Exceptions: -* Input parameters are validated. Refer to the validation section of the function. -* -*******************************************************************************/ - -extern "C" void* __cdecl _aligned_recalloc_base( +extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_realloc( void* const block, - size_t const count, size_t const size, - size_t const alignment - ) -{ - return _aligned_offset_recalloc_base(block, count, size, alignment, 0); -} - -/*** -* -* void *_aligned_offset_realloc_base (void * memblock, size_t size, -* size_t alignment, int offset) -* - Reallocate a block of memory from the heap. -* -* Purpose: -* Reallocates a block of memory which is shifted by offset from -* alignment of at least size bytes from the heap and return a pointer -* to it. Size can be either greater or less than the original size of the -* block. -* -* Entry: -* void *memblock - pointer to block in the heap previously allocated by -* call to _aligned_malloc(), _aligned_offset_malloc(), -* _aligned_realloc() or _aligned_offset_realloc(). -* size_t size - size of block of memory -* size_t alignment - alignment of memory -* size_t offset - offset of memory from the alignment -* -* Exit: -* Success: Pointer to re-allocated memory block -* Failure: Null, errno is set -* -* Exceptions: -* Input parameters are validated. Refer to the validation section of the function. -* -*******************************************************************************/ - -extern "C" void* __cdecl _aligned_offset_realloc_base( - void* block, - size_t size, - size_t align, - size_t offset + size_t const alignment, + size_t const offset ) { uintptr_t ptr, retptr, gap, stptr, diff; uintptr_t movsz, reqsz; + size_t align = alignment; int bFree = 0; /* special cases */ if (block == nullptr) { - return _aligned_offset_malloc_base(size, align, offset); + return _aligned_offset_malloc(size, align, offset); } if (size == 0) { - _aligned_free_base(block); + _aligned_free(block); return nullptr; } @@ -323,7 +186,7 @@ extern "C" void* __cdecl _aligned_offset_realloc_base( */ #pragma warning(push) #pragma warning(disable: 22018) // Silence prefast about overflow/underflow - movsz = _msize_base((void *)stptr) - ((uintptr_t)block - stptr); + movsz = _msize((void *)stptr) - ((uintptr_t)block - stptr); #pragma warning(pop) movsz = movsz > size ? size : movsz; @@ -377,99 +240,19 @@ extern "C" void* __cdecl _aligned_offset_realloc_base( return (void *)retptr; } - -/*** -* -* size_t _aligned_msize_base(void *memblock, size_t align, size_t offset) -* -* Purpose: -* Computes the size of an aligned block. -* -* Entry: -* void * memblock - pointer to the aligned block of memory -* -* Exceptions: -* None. If memblock == nullptr 0 is returned. -* -*******************************************************************************/ - -extern "C" size_t __cdecl _aligned_msize_base( - void* block, - size_t align, - size_t offset - ) -{ - size_t header_size = 0; /* Size of the header block */ - size_t footer_size = 0; /* Size of the footer block */ - size_t total_size = 0; /* total size of the allocated block */ - size_t user_size = 0; /* size of the user block*/ - uintptr_t gap = 0; /* keep the alignment of the data block */ - /* after the sizeof(void*) aligned pointer */ - /* to the beginning of the allocated block */ - uintptr_t ptr = 0; /* computes the beginning of the allocated block */ - - _VALIDATE_RETURN(block != nullptr, EINVAL, static_cast(-1)); - - /* HEADER SIZE + FOOTER SIZE = GAP + ALIGN + SIZE OF A POINTER*/ - /* HEADER SIZE + USER SIZE + FOOTER SIZE = TOTAL SIZE */ - - ptr = (uintptr_t)block; /* ptr points to the start of the aligned memory block */ - ptr = (ptr & ~(PTR_SZ - 1)) - PTR_SZ; /* ptr is one position behind memblock */ - /* the value in ptr is the start of the real allocated block */ - ptr = *((uintptr_t *)ptr); /* after dereference ptr points to the beginning of the allocated block */ - - total_size = _msize_base((void*)ptr); - header_size = (uintptr_t) block - ptr; - gap = (0 - offset) & (PTR_SZ - 1); - /* Alignment cannot be less than sizeof(void*) */ - align = (align > PTR_SZ ? align : PTR_SZ) -1; - footer_size = gap + align + PTR_SZ - header_size; - user_size = total_size - header_size - footer_size; - - return user_size; -} - -/*** -* -* void *_aligned_offset_recalloc_base (void * memblock, size_t size, size_t count, size_t alignment, int offset) -* - Reallocate a block of memory from the heap. -* -* Purpose: -* Reallocates a block of memory which is shifted by offset from -* alignment of at least size bytes from the heap and return a pointer -* to it. Size can be either greater or less than the original size of the -* block. -* -* Entry: -* void *memblock - pointer to block in the heap previously allocated by -* call to _aligned_malloc(), _aligned_offset_malloc(), -* _aligned_realloc() or _aligned_offset_realloc(). -* size_t count - count of items -* size_t size - size of items -* size_t alignment - alignment of memory -* size_t offset - offset of memory from the alignment -* -* Exit: -* Success: Pointer to re-allocated memory block -* Failure: Null, errno is set -* -* Exceptions: -* Input parameters are validated. Refer to the validation section of the function. -* -*******************************************************************************/ - -extern "C" void* __cdecl _aligned_offset_recalloc_base( - void* block, - size_t count, - size_t size, - size_t align, - size_t offset +extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_recalloc( + void* const block, + size_t const count, + size_t const size, + size_t const alignment, + size_t const offset ) { - size_t user_size = 0; /* wanted size, passed to aligned realoc */ - size_t start_fill = 0; /* location where aligned recalloc starts to fill with 0 */ - /* filling must start from the end of the previous user block */ - void * retptr = nullptr; /* result of aligned recalloc*/ + size_t align = alignment; + size_t user_size = 0; /* wanted size, passed to aligned realoc */ + size_t start_fill = 0; /* location where aligned recalloc starts to fill with 0 */ + /* filling must start from the end of the previous user block */ + void* retptr = nullptr; /* result of aligned recalloc*/ /* ensure that (size * num) does not overflow */ if (count > 0) @@ -481,146 +264,28 @@ extern "C" void* __cdecl _aligned_offset_recalloc_base( if (block != nullptr) { - start_fill = _aligned_msize_base(block, align, offset); + start_fill = _aligned_msize(block, align, offset); } - retptr = _aligned_offset_realloc_base(block, user_size, align, offset); + retptr = _aligned_offset_realloc(block, user_size, align, offset); if (retptr != nullptr) { if (start_fill < user_size) { - memset ((char*)retptr + start_fill, 0, user_size - start_fill); + memset((char*)retptr + start_fill, 0, user_size - start_fill); } } return retptr; } -/*** -* -* void *_aligned_free_base(void *memblock) -* - Free the memory which was allocated using _aligned_malloc or -* _aligned_offset_memory -* -* Purpose: -* Frees the aligned memory block which was allocated using _aligned_malloc. -* -* Entry: -* void * memblock - pointer to the block of memory -* -* Exceptions: -* None. If memblock == nullptr we simply return without doing anything. -* -*******************************************************************************/ - -extern "C" void __cdecl _aligned_free_base(void* const block) -{ - uintptr_t ptr; - - if (block == nullptr) - return; - - ptr = (uintptr_t)block; - - /* ptr points to the pointer to starting of the memory block */ - ptr = (ptr & ~(PTR_SZ -1)) - PTR_SZ; - - /* ptr is the pointer to the start of memory block*/ - ptr = *((uintptr_t*)ptr); - free((void *)ptr); -} - -// These functions are patchable and therefore must be marked noinline. -// Their *_base implementations are marked __forceinline in order to -// ensure each export is separated from each other and that there is -// enough space in each export to host a patch. - -extern "C" __declspec(noinline) void __cdecl _aligned_free(void* const block) -{ - #ifdef _DEBUG - _aligned_free_dbg(block); - #else - _aligned_free_base(block); - #endif -} - -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_malloc( - size_t const size, - size_t const alignment - ) -{ - #ifdef _DEBUG - return _aligned_offset_malloc_dbg(size, alignment, 0, nullptr, 0); - #else - return _aligned_malloc_base(size, alignment); - #endif -} - -extern "C" __declspec(noinline) size_t __cdecl _aligned_msize( - void* const block, - size_t const alignment, - size_t const offset) -{ - #ifdef _DEBUG - return _aligned_msize_dbg(block, alignment, offset); - #else - return _aligned_msize_base(block, alignment, offset); - #endif -} - -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_malloc( - size_t const size, - size_t const alignment, - size_t const offset - ) -{ - #ifdef _DEBUG - return _aligned_offset_malloc_dbg(size, alignment, offset, nullptr, 0); - #else - return _aligned_offset_malloc_base(size, alignment, offset); - #endif -} - -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_realloc( - void* const block, - size_t const size, - size_t const alignment, - size_t const offset - ) -{ - #ifdef _DEBUG - return _aligned_offset_realloc_dbg(block, size, alignment, offset, nullptr, 0); - #else - return _aligned_offset_realloc_base(block, size, alignment, offset); - #endif -} - -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_offset_recalloc( - void* const block, - size_t const count, - size_t const size, - size_t const alignment, - size_t const offset - ) -{ - #ifdef _DEBUG - return _aligned_offset_recalloc_dbg(block, count, size, alignment, offset, nullptr, 0); - #else - return _aligned_offset_recalloc_base(block, count, size, alignment, offset); - #endif -} - extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_realloc( void* const block, size_t const size, size_t const alignment ) { - #ifdef _DEBUG - return _aligned_offset_realloc_dbg(block, size, alignment, 0, nullptr, 0); - #else - return _aligned_realloc_base(block, size, alignment); - #endif + return _aligned_offset_realloc(block, size, alignment, 0); } extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_recalloc( @@ -630,9 +295,5 @@ extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _aligned_recalloc( size_t const alignment ) { - #ifdef _DEBUG - return _aligned_offset_recalloc_dbg(block, count, size, alignment, 0, nullptr, 0); - #else - return _aligned_recalloc_base(block, count, size, alignment); - #endif + return _aligned_offset_recalloc(block, count, size, alignment, 0); } diff --git a/src/ucrt/heap/calloc.cpp b/src/ucrt/heap/calloc.cpp index a4e9db7..66c1aa6 100644 --- a/src/ucrt/heap/calloc.cpp +++ b/src/ucrt/heap/calloc.cpp @@ -8,6 +8,7 @@ // #include #include +#include // Allocates a block of memory of size 'count * size' in the heap. The newly // allocated block is zero-initialized. If allocation fails, nullptr is @@ -22,9 +23,34 @@ extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) _CRTRESTRICT void* __cdecl size_t const size ) { -#ifdef _DEBUG - return _calloc_dbg(count, size, _NORMAL_BLOCK, nullptr, 0); -#else - return _calloc_base(count, size); -#endif + // Ensure that (count * size) does not overflow + _VALIDATE_RETURN_NOEXC(count == 0 || (_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr); + + // Ensure that we allocate a nonzero block size: + size_t const requested_block_size = count * size; + size_t const actual_block_size = requested_block_size == 0 + ? 1 + : requested_block_size; + + for (;;) + { + void* const block = malloc(actual_block_size); + + // If allocation succeeded, return the pointer to the new block: + if (block) + { + memset(block, 0, actual_block_size); + return block; + } + + // Otherwise, see if we need to call the new handler, and if so call it. + // If the new handler fails, just return nullptr: + if (_query_new_mode() == 0 || !_callnewh(actual_block_size)) + { + errno = ENOMEM; + return nullptr; + } + + // The new handler was successful; try to allocate aagain... + } } diff --git a/src/ucrt/heap/calloc_base.cpp b/src/ucrt/heap/calloc_base.cpp deleted file mode 100644 index 2d2f71b..0000000 --- a/src/ucrt/heap/calloc_base.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// -// calloc_base.cpp -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Implementation of _calloc_base(). This is defined in a different source file -// from the calloc() function to allow calloc() to be replaced by the user. -// -#include -#include -#include - -// This function implements the logic of calloc(). -// -// This function must be marked noinline, otherwise calloc and -// _calloc_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because calloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _calloc_base( - size_t const count, - size_t const size - ) -{ - // Ensure that (count * size) does not overflow - _VALIDATE_RETURN_NOEXC(count == 0 || (_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr); - - // Ensure that we allocate a nonzero block size: - size_t const requested_block_size = count * size; - size_t const actual_block_size = requested_block_size == 0 - ? 1 - : requested_block_size; - - for (;;) - { - void* const block = malloc(actual_block_size); - - // If allocation succeeded, return the pointer to the new block: - if (block) - { - memset(block, 0, actual_block_size); - return block; - } - - // Otherwise, see if we need to call the new handler, and if so call it. - // If the new handler fails, just return nullptr: - if (_query_new_mode() == 0 || !_callnewh(actual_block_size)) - { - errno = ENOMEM; - return nullptr; - } - - // The new handler was successful; try to allocate aagain... - } -} diff --git a/src/ucrt/heap/debug_heap.cpp b/src/ucrt/heap/debug_heap.cpp deleted file mode 100644 index 3853d0e..0000000 --- a/src/ucrt/heap/debug_heap.cpp +++ /dev/null @@ -1,339 +0,0 @@ -// -// debug_heap.cpp -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// The implementation of the CRT Debug Heap. -// -#ifndef _DEBUG - #error This file is supported only in debug builds - #define _DEBUG // For design-time support, when editing/viewing CRT sources -#endif - -#include -#include -#include -#include -#include -#include - - - -//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// Constant Data -// -//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -#define _ALLOCATION_FILE_LINENUM "\nMemory allocated at %hs(%d).\n" - -#if _FREE_BLOCK != 0 || _NORMAL_BLOCK != 1 || _CRT_BLOCK != 2 || _IGNORE_BLOCK != 3 || _CLIENT_BLOCK != 4 - #error Block numbers have changed! -#endif - -//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// Public Debug Heap Allocation APIs -// -//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -_Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Size) -_ACRTIMP _CRTALLOCATOR _CRT_HYBRIDPATCHABLE -extern "C" void* __cdecl _expand_base( - _Pre_notnull_ void* _Block, - _In_ size_t _Size -); - -// These are the allocation functions that allocate, manipulate, and free blocks -// from the debug heap. They are equivalent to the main allocation functions, -// which deal with blocks from the process heap. Most of the debug allocation -// functions accept a block use, file name, and/or line number which are used to -// track where allocations originated. -// -// Documentation comments for these functions describe only the material -// differences between them and the corresponding main allocation functions. - -// This function must be marked noinline, otherwise malloc and -// _malloc_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because malloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _malloc_dbg( - size_t const size, - int const block_use, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _malloc_base(size); -} - - -// This function must be marked noinline, otherwise calloc and -// _calloc_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because calloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _calloc_dbg( - size_t const count, - size_t const element_size, - int const block_use, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _calloc_base(count, element_size); -} - - -// This function must be marked noinline, otherwise realloc and -// _realloc_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because realloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _realloc_dbg( - void* const block, - size_t const requested_size, - int const block_use, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _realloc_base(block, requested_size); -} - - -// This function must be marked noinline, otherwise recalloc and -// _recalloc_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because recalloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _recalloc_dbg( - void* const block, - size_t const count, - size_t const element_size, - int const block_use, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _recalloc_base(block, count, element_size); -} - -// This function must be marked noinline, otherwise _expand and -// _expand_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because _expand -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _expand_dbg( - void* const block, - size_t const requested_size, - int const block_use, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _expand_base(block, requested_size); -} - - - -// This function must be marked noinline, otherwise free and -// _free_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because free -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void __cdecl _free_dbg(void* const block, int const block_use) -{ - UNREFERENCED_PARAMETER(block_use); - - return _free_base(block); -} - - -// This function must be marked noinline, otherwise _msize and -// _msize_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because _msize -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) size_t __cdecl _msize_dbg(void* const block, int const block_use) -{ - UNREFERENCED_PARAMETER(block_use); - - return _msize_base(block); -} - - - -//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// -// Aligned Allocation -// -//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - -extern "C" void __cdecl _aligned_free_base( - _Pre_maybenull_ _Post_invalid_ void* block -); - -_Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_malloc_base( - _In_ size_t size, - _In_ size_t alignment -); - -_Check_return_ -extern "C" size_t __cdecl _aligned_msize_base( - _Pre_notnull_ void* block, - _In_ size_t alignment, - _In_ size_t offset -); - -_Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_offset_malloc_base( - _In_ size_t size, - _In_ size_t alignment, - _In_ size_t offset -); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_offset_realloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t size, - _In_ size_t alignment, - _In_ size_t offset -); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size * count) -extern "C" void* __cdecl _aligned_offset_recalloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t count, - _In_ size_t size, - _In_ size_t alignment, - _In_ size_t offset -); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size) -extern "C" void* __cdecl _aligned_realloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t size, - _In_ size_t alignment -); - -_Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(size * count) -extern "C" void* __cdecl _aligned_recalloc_base( - _Pre_maybenull_ _Post_invalid_ void* block, - _In_ size_t count, - _In_ size_t size, - _In_ size_t alignment -); - - -#define IS_2_POW_N(X) ((X) != 0 && ((X) & ((X) - 1)) == 0) - - -extern "C" void* __cdecl _aligned_malloc_dbg( - size_t const size, - size_t const alignment, - char const* const file_name, - int const line_number - ) -{ - return _aligned_offset_malloc_dbg(size, alignment, 0, file_name, line_number); -} - -extern "C" void* __cdecl _aligned_offset_malloc_dbg( - size_t const size, - size_t alignment, - size_t const offset, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _aligned_offset_malloc_base(size, alignment, offset); -} - -extern "C" void* __cdecl _aligned_realloc_dbg( - void* const block, - size_t const size, - size_t const alignment, - char const* const file_name, - int const line_number - ) -{ - return _aligned_offset_realloc_dbg(block, size, alignment, 0, file_name, line_number); -} - -extern "C" void* __cdecl _aligned_recalloc_dbg( - void* const block, - size_t const count, - size_t const size, - size_t const alignment, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _aligned_offset_recalloc_dbg(block, count, size, alignment, 0, file_name, line_number); -} - -extern "C" void* __cdecl _aligned_offset_realloc_dbg( - void * block, - size_t size, - size_t alignment, - size_t offset, - const char * file_name, - int line_number - ) -{ - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _aligned_offset_realloc_base(block, size, alignment, offset); -} - -extern "C" size_t __cdecl _aligned_msize_dbg( - void* const block, - size_t alignment, - size_t const offset - ) -{ - return _aligned_msize_base(block, alignment, offset); -} - -extern "C" void* __cdecl _aligned_offset_recalloc_dbg( - void* const block, - size_t const count, - size_t const element_size, - size_t const alignment, - size_t const offset, - char const* const file_name, - int const line_number - ) -{ - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _aligned_offset_recalloc_base(block, count, element_size, alignment, offset); -} - -extern "C" void __cdecl _aligned_free_dbg(void* const block) -{ - return _aligned_free_base(block); -} diff --git a/src/ucrt/heap/expand.cpp b/src/ucrt/heap/expand.cpp index 9d651fc..7d0bcfe 100644 --- a/src/ucrt/heap/expand.cpp +++ b/src/ucrt/heap/expand.cpp @@ -9,31 +9,6 @@ #include - -// This function implements the logic of expand(). It is called directly by the -// _expand() function in the Release CRT, and called by the debug heap in the -// Debug CRT. -// -// This function must be marked noinline, otherwise _expand and -// _expand_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because _expand -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _expand_base(void* const block, size_t const size) -{ - // Validation section - _VALIDATE_RETURN (block != nullptr, EINVAL, nullptr); - _VALIDATE_RETURN_NOEXC(size <= _HEAP_MAXREQ, ENOMEM, nullptr); - - size_t const new_size = size == 0 ? 1 : size; - - void* new_block = _realloc_base(block, new_size); - if (new_block != nullptr) - return new_block; - - errno = __acrt_errno_from_os_error(STATUS_INSUFFICIENT_RESOURCES); - return nullptr; -} - // Expands or contracts a block of memory in the heap. // // This function resizes a block of memory in the heap to 'size' bytes. The @@ -48,9 +23,16 @@ extern "C" __declspec(noinline) void* __cdecl _expand_base(void* const block, si // with either other function or vice versa. extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) void* __cdecl _expand(void* const block, size_t const size) { -#ifdef _DEBUG - return _expand_dbg(block, size, _NORMAL_BLOCK, nullptr, 0); -#else - return _expand_base(block, size); -#endif + // Validation section + _VALIDATE_RETURN(block != nullptr, EINVAL, nullptr); + _VALIDATE_RETURN_NOEXC(size <= _HEAP_MAXREQ, ENOMEM, nullptr); + + size_t const new_size = size == 0 ? 1 : size; + + void* new_block = realloc(block, new_size); + if (new_block != nullptr) + return new_block; + + errno = __acrt_errno_from_os_error(STATUS_INSUFFICIENT_RESOURCES); + return nullptr; } diff --git a/src/ucrt/heap/free.cpp b/src/ucrt/heap/free.cpp index b99c653..cc62e8d 100644 --- a/src/ucrt/heap/free.cpp +++ b/src/ucrt/heap/free.cpp @@ -17,9 +17,8 @@ // with either other function or vice versa. extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) void __cdecl free(void* const block) { -#ifdef _DEBUG - _free_dbg(block, _NORMAL_BLOCK); -#else - _free_base(block); -#endif + if (block) + { + ExFreePoolWithTag(block, __ucxxrt_tag); + } } diff --git a/src/ucrt/heap/free_base.cpp b/src/ucrt/heap/free_base.cpp deleted file mode 100644 index b96c108..0000000 --- a/src/ucrt/heap/free_base.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// -// free_base.cpp -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Implementation of _free_base(). This is defined in a different source file -// from the free() function to allow free() to be replaced by the user. -// -#include -#include - - - -// This function implements the logic of free(). It is called directly by the -// free() function in the Release CRT, and it is called by the debug heap in the -// Debug CRT. -// -// This function must be marked noinline, otherwise free and -// _free_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because free -// needs to support users patching in custom implementations. -extern "C" void __declspec(noinline) __cdecl _free_base(void* const block) -{ - if (block) - { - ExFreePoolWithTag(block, __ucxxrt_tag); - } -} - diff --git a/src/ucrt/heap/free_km.cpp b/src/ucrt/heap/free_km.cpp deleted file mode 100644 index 6a66373..0000000 --- a/src/ucrt/heap/free_km.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * PROJECT: Universal C++ RunTime (UCXXRT) - * FILE: free_km.cpp - * DATA: 2022/06/17 - * - * PURPOSE: Universal C++ RunTime - * - * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License - * - * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) - */ - -#include -#include - - -// This function implements the logic of kfree(). It is called directly by the -// kfree() function in the Release CRT, and it is called by the debug heap in the -// Debug CRT. -// -// This function must be marked noinline, otherwise free and -// _kfree_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because free -// needs to support users patching in custom implementations. -extern "C" void __declspec(noinline) __cdecl _kfree_base(void* const block, unsigned long tag) -{ - if (block) - { - ExFreePoolWithTag(block, tag); - } -} - - -#ifdef _DEBUG -// This function must be marked noinline, otherwise kfree and -// _kfree_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because free -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void __cdecl _kfree_dbg(void* const block, unsigned long tag, int const block_use) -{ - UNREFERENCED_PARAMETER(block_use); - - return _kfree_base(block, tag); -} -#endif - - -// Frees a block in the heap. The 'block' pointer must either be a null pointer -// or must point to a valid block in the heap. -// -// This function supports patching and therefore must be marked noinline. -// Both _kfree_dbg and _kfree_base must also be marked noinline -// to prevent identical COMDAT folding from substituting calls to free -// with either other function or vice versa. -extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) void __cdecl kfree(void* const block, unsigned long tag) -{ -#ifdef _DEBUG - _kfree_dbg(block, tag, _NORMAL_BLOCK); -#else - _kfree_base(block, tag); -#endif -} diff --git a/src/ucrt/heap/calloc_km.cpp b/src/ucrt/heap/kcalloc.cpp similarity index 57% rename from src/ucrt/heap/calloc_km.cpp rename to src/ucrt/heap/kcalloc.cpp index 1595811..d921543 100644 --- a/src/ucrt/heap/calloc_km.cpp +++ b/src/ucrt/heap/kcalloc.cpp @@ -11,22 +11,25 @@ */ #include -#include +#include #include -// This function implements the logic of calloc(). + +// Allocates a block of memory of size 'count * size' in the heap. The newly +// allocated block is zero-initialized. If allocation fails, nullptr is +// returned. // -// This function must be marked noinline, otherwise calloc and -// _calloc_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because calloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _kcalloc_base( +// This function supports patching and therefore must be marked noinline. +// Both _calloc_dbg and _calloc_base must also be marked noinline +// to prevent identical COMDAT folding from substituting calls to calloc +// with either other function or vice versa. +extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) _CRTRESTRICT void* __cdecl kcalloc( size_t const count, size_t const size, int pool_type, unsigned long tag -) + ) { // Ensure that (count * size) does not overflow _VALIDATE_RETURN_NOEXC(count == 0 || (_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr); @@ -59,48 +62,3 @@ extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _kcalloc_base( // The new handler was successful; try to allocate aagain... } } - - -// This function must be marked noinline, otherwise calloc and -// _calloc_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because calloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _kcalloc_dbg( - size_t const count, - size_t const element_size, - int pool_type, - unsigned long tag, - int const block_use, - char const* const file_name, - int const line_number -) -{ - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _kcalloc_base(count, element_size, pool_type, tag); -} - - -// Allocates a block of memory of size 'count * size' in the heap. The newly -// allocated block is zero-initialized. If allocation fails, nullptr is -// returned. -// -// This function supports patching and therefore must be marked noinline. -// Both _calloc_dbg and _calloc_base must also be marked noinline -// to prevent identical COMDAT folding from substituting calls to calloc -// with either other function or vice versa. -extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) _CRTRESTRICT void* __cdecl kcalloc( - size_t const count, - size_t const size, - int pool_type, - unsigned long tag - ) -{ -#ifdef _DEBUG - return _kcalloc_dbg(count, size, pool_type, tag, _NORMAL_BLOCK, nullptr, 0); -#else - return _kcalloc_base(count, size, pool_type, tag); -#endif -} diff --git a/src/ucrt/heap/kfree.cpp b/src/ucrt/heap/kfree.cpp new file mode 100644 index 0000000..cd37c01 --- /dev/null +++ b/src/ucrt/heap/kfree.cpp @@ -0,0 +1,30 @@ +/* + * PROJECT: Universal C++ RunTime (UCXXRT) + * FILE: free_km.cpp + * DATA: 2022/06/17 + * + * PURPOSE: Universal C++ RunTime + * + * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License + * + * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) + */ + +#include +#include + + +// Frees a block in the heap. The 'block' pointer must either be a null pointer +// or must point to a valid block in the heap. +// +// This function supports patching and therefore must be marked noinline. +// Both _kfree_dbg and _kfree_base must also be marked noinline +// to prevent identical COMDAT folding from substituting calls to free +// with either other function or vice versa. +extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) void __cdecl kfree(void* const block, unsigned long tag) +{ + if (block) + { + ExFreePoolWithTag(block, tag); + } +} diff --git a/src/ucrt/heap/kmalloc.cpp b/src/ucrt/heap/kmalloc.cpp new file mode 100644 index 0000000..b983591 --- /dev/null +++ b/src/ucrt/heap/kmalloc.cpp @@ -0,0 +1,55 @@ +/* + * PROJECT: Universal C++ RunTime (UCXXRT) + * FILE: malloc_km.cpp + * DATA: 2022/06/17 + * + * PURPOSE: Universal C++ RunTime + * + * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License + * + * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) + */ + +#include +#include +#include + + + +// Allocates a block of memory of size 'size' bytes in the heap. If allocation +// fails, nullptr is returned. +// +// This function supports patching and therefore must be marked noinline. +// Both _kmalloc_dbg and _kmalloc_base must also be marked noinline +// to prevent identical COMDAT folding from substituting calls to malloc +// with either other function or vice versa. +extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) _CRTRESTRICT void* __cdecl kmalloc( + size_t const size, + int pool_type, + unsigned long tag +) +{ + // Ensure that the requested size is not too large: + _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr); + + // Ensure we request an allocation of at least one byte: + size_t const actual_size = size == 0 ? 1 : size; + + for (;;) + { + #pragma warning(suppress: 4996) + void* const block = ExAllocatePoolWithTag((POOL_TYPE)pool_type, actual_size, tag); + if (block) + return block; + + // Otherwise, see if we need to call the new handler, and if so call it. + // If the new handler fails, just return nullptr: + if (_query_new_mode() == 0 || !_callnewh(actual_size)) + { + errno = ENOMEM; + return nullptr; + } + + // The new handler was successful; try to allocate again... + } +} diff --git a/src/ucrt/heap/malloc.cpp b/src/ucrt/heap/malloc.cpp index e36fc4f..67be313 100644 --- a/src/ucrt/heap/malloc.cpp +++ b/src/ucrt/heap/malloc.cpp @@ -7,6 +7,7 @@ // #include #include +#include @@ -19,9 +20,27 @@ // with either other function or vice versa. extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) _CRTRESTRICT void* __cdecl malloc(size_t const size) { -#ifdef _DEBUG - return _malloc_dbg(size, _NORMAL_BLOCK, nullptr, 0); -#else - return _malloc_base(size); -#endif + // Ensure that the requested size is not too large: + _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr); + + // Ensure we request an allocation of at least one byte: + size_t const actual_size = size == 0 ? 1 : size; + + for (;;) + { + #pragma warning(suppress: 4996) + void* const block = ExAllocatePoolWithTag(NonPagedPool, actual_size, __ucxxrt_tag); + if (block) + return block; + + // Otherwise, see if we need to call the new handler, and if so call it. + // If the new handler fails, just return nullptr: + if (_query_new_mode() == 0 || !_callnewh(actual_size)) + { + errno = ENOMEM; + return nullptr; + } + + // The new handler was successful; try to allocate again... + } } diff --git a/src/ucrt/heap/malloc_base.cpp b/src/ucrt/heap/malloc_base.cpp deleted file mode 100644 index b3e7433..0000000 --- a/src/ucrt/heap/malloc_base.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// malloc_base.cpp -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Implementation of _malloc_base(). This is defined in a different source file -// from the malloc() function to allow malloc() to be replaced by the user. -// -#include -#include -#include - - - -// This function implements the logic of malloc(). It is called directly by the -// malloc() function in the Release CRT and is called by the debug heap in the -// Debug CRT. -// -// This function must be marked noinline, otherwise malloc and -// _malloc_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because malloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _malloc_base(size_t const size) -{ - // Ensure that the requested size is not too large: - _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr); - - // Ensure we request an allocation of at least one byte: - size_t const actual_size = size == 0 ? 1 : size; - - for (;;) - { -#pragma warning(suppress: 4996) - void* const block = ExAllocatePoolWithTag(NonPagedPool, actual_size, __ucxxrt_tag); - if (block) - return block; - - // Otherwise, see if we need to call the new handler, and if so call it. - // If the new handler fails, just return nullptr: - if (_query_new_mode() == 0 || !_callnewh(actual_size)) - { - errno = ENOMEM; - return nullptr; - } - - // The new handler was successful; try to allocate again... - } -} diff --git a/src/ucrt/heap/malloc_km.cpp b/src/ucrt/heap/malloc_km.cpp deleted file mode 100644 index 645288e..0000000 --- a/src/ucrt/heap/malloc_km.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * PROJECT: Universal C++ RunTime (UCXXRT) - * FILE: malloc_km.cpp - * DATA: 2022/06/17 - * - * PURPOSE: Universal C++ RunTime - * - * LICENSE: Relicensed under The MIT License from The CC BY 4.0 License - * - * DEVELOPER: MiroKaku (miro.kaku AT Outlook.com) - */ - -#include -#include -#include - - -// This function implements the logic of kmalloc(). It is called directly by the -// kmalloc() function in the Release CRT and is called by the debug heap in the -// Debug CRT. -// -// This function must be marked noinline, otherwise malloc and -// _kmalloc_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because malloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _kmalloc_base(size_t const size, int pool_type, unsigned long tag) -{ - // Ensure that the requested size is not too large: - _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr); - - // Ensure we request an allocation of at least one byte: - size_t const actual_size = size == 0 ? 1 : size; - - for (;;) - { -#pragma warning(suppress: 4996) - void* const block = ExAllocatePoolWithTag((POOL_TYPE)pool_type, actual_size, tag); - if (block) - return block; - - // Otherwise, see if we need to call the new handler, and if so call it. - // If the new handler fails, just return nullptr: - if (_query_new_mode() == 0 || !_callnewh(actual_size)) - { - errno = ENOMEM; - return nullptr; - } - - // The new handler was successful; try to allocate again... - } -} - -#ifdef _DEBUG -// These are the allocation functions that allocate, manipulate, and free blocks -// from the debug heap. They are equivalent to the main allocation functions, -// which deal with blocks from the process heap. Most of the debug allocation -// functions accept a block use, file name, and/or line number which are used to -// track where allocations originated. -// -// Documentation comments for these functions describe only the material -// differences between them and the corresponding main allocation functions. - -// This function must be marked noinline, otherwise kmalloc and -// _kmalloc_dbg will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because malloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) void* __cdecl _kmalloc_dbg( - size_t const size, - int pool_type, - unsigned long tag, - int const block_use, - char const* const file_name, - int const line_number -) -{ - UNREFERENCED_PARAMETER(block_use); - UNREFERENCED_PARAMETER(file_name); - UNREFERENCED_PARAMETER(line_number); - - return _kmalloc_base(size, pool_type, tag); -} -#endif - -// Allocates a block of memory of size 'size' bytes in the heap. If allocation -// fails, nullptr is returned. -// -// This function supports patching and therefore must be marked noinline. -// Both _kmalloc_dbg and _kmalloc_base must also be marked noinline -// to prevent identical COMDAT folding from substituting calls to malloc -// with either other function or vice versa. -extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) _CRTRESTRICT void* __cdecl kmalloc( - size_t const size, - int pool_type, - unsigned long tag -) -{ -#ifdef _DEBUG - return _kmalloc_dbg(size, pool_type, tag, _NORMAL_BLOCK, nullptr, 0); -#else - return _kmalloc_base(size, pool_type, tag); -#endif -} diff --git a/src/ucrt/heap/msize.cpp b/src/ucrt/heap/msize.cpp index 15f5723..6d75d2a 100644 --- a/src/ucrt/heap/msize.cpp +++ b/src/ucrt/heap/msize.cpp @@ -10,14 +10,14 @@ -// This function implements the logic of _msize(). It is called only in the -// Release CRT. The Debug CRT has its own implementation of this function. +// Calculates the size of the specified block in the heap. 'block' must be a +// pointer to a valid block of heap-allocated memory (it must not be nullptr). // -// This function must be marked noinline, otherwise _msize and -// _msize_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because _msize -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) size_t __cdecl _msize_base(void* const block) _CRT_NOEXCEPT +// This function supports patching and therefore must be marked noinline. +// Both _msize_dbg and _msize_base must also be marked noinline +// to prevent identical COMDAT folding from substituting calls to _msize +// with either other function or vice versa. +extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) size_t __cdecl _msize(void* const block) { size_t size = 0; BOOLEAN quota_charged = FALSE; @@ -32,25 +32,8 @@ extern "C" __declspec(noinline) size_t __cdecl _msize_base(void* const block) _C // rather than the correct number of bytes. size = 0; - KdBreakPoint(); } return size; } - -// Calculates the size of the specified block in the heap. 'block' must be a -// pointer to a valid block of heap-allocated memory (it must not be nullptr). -// -// This function supports patching and therefore must be marked noinline. -// Both _msize_dbg and _msize_base must also be marked noinline -// to prevent identical COMDAT folding from substituting calls to _msize -// with either other function or vice versa. -extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) size_t __cdecl _msize(void* const block) -{ -#ifdef _DEBUG - return _msize_dbg(block, _NORMAL_BLOCK); -#else - return _msize_base(block); -#endif -} diff --git a/src/ucrt/heap/realloc.cpp b/src/ucrt/heap/realloc.cpp index 5f70c56..0b21757 100644 --- a/src/ucrt/heap/realloc.cpp +++ b/src/ucrt/heap/realloc.cpp @@ -7,6 +7,36 @@ // #include #include +#include + + + +extern"C" __declspec(noinline) void* __cdecl ExReallocatePoolWithTag( + _In_ SIZE_T OldSize, + _In_ SIZE_T NewSize, + _In_ PVOID OldBlock, + _In_ __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType, + _In_ ULONG Tag +) +{ + if (OldSize == 0) + { + return nullptr; + } + +#pragma warning(suppress: 4996) + void* const NewBlock = ExAllocatePoolWithTag(PoolType, NewSize, Tag); + if (NewBlock) + { + memset(NewBlock, 0, NewSize); + memmove(NewBlock, OldBlock, OldSize); + + ExFreePoolWithTag(OldBlock, Tag); + return NewBlock; + } + + return nullptr; +} // Reallocates a block of memory in the heap. // @@ -33,9 +63,36 @@ extern "C" _CRT_HYBRIDPATCHABLE __declspec(noinline) _CRTRESTRICT void* __cdecl size_t const size ) { -#ifdef _DEBUG - return _realloc_dbg(block, size, _NORMAL_BLOCK, nullptr, 0); -#else - return _realloc_base(block, size); -#endif + // If the block is a nullptr, just call malloc: + if (block == nullptr) + return malloc(size); + + // If the new size is 0, just call free and return nullptr: + if (size == 0) + { + free(block); + return nullptr; + } + + // Ensure that the requested size is not too large: + _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr); + + for (;;) + { + void* const new_block = ExReallocatePoolWithTag(_msize(block), size, block, NonPagedPool, __ucxxrt_tag); + if (new_block) + { + return new_block; + } + + // Otherwise, see if we need to call the new handler, and if so call it. + // If the new handler fails, just return nullptr: + if (_query_new_mode() == 0 || !_callnewh(size)) + { + errno = ENOMEM; + return nullptr; + } + + // The new handler was successful; try to allocate again... + } } diff --git a/src/ucrt/heap/realloc_base.cpp b/src/ucrt/heap/realloc_base.cpp deleted file mode 100644 index f4b0614..0000000 --- a/src/ucrt/heap/realloc_base.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// -// realloc_base.cpp -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// Implementation of _realloc_base(). This is defined in a different source -// file from the realloc() function to allow realloc() to be replaced by the -// user. -// -#include -#include -#include - - -extern"C" __declspec(noinline) void* __cdecl ExReallocatePoolWithTag( - _In_ SIZE_T OldSize, - _In_ SIZE_T NewSize, - _In_ PVOID OldBlock, - _In_ __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType, - _In_ ULONG Tag -) -{ - if (OldSize == 0) - { - return nullptr; - } - -#pragma warning(suppress: 4996) - void* const NewBlock = ExAllocatePoolWithTag(PoolType, NewSize, Tag); - if (NewBlock) - { - memset (NewBlock, 0, NewSize); - memmove(NewBlock, OldBlock, OldSize); - - ExFreePoolWithTag(OldBlock, Tag); - return NewBlock; - } - - return nullptr; -} - - -// This function implements the logic of realloc(). It is called directly by -// the realloc() and _recalloc() functions in the Release CRT and is called by -// the debug heap in the Debug CRT. -// -// This function must be marked noinline, otherwise realloc and -// _realloc_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because realloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _realloc_base( - void* const block, - size_t const size - ) -{ - // If the block is a nullptr, just call malloc: - if (block == nullptr) - return _malloc_base(size); - - // If the new size is 0, just call free and return nullptr: - if (size == 0) - { - _free_base(block); - return nullptr; - } - - // Ensure that the requested size is not too large: - _VALIDATE_RETURN_NOEXC(_HEAP_MAXREQ >= size, ENOMEM, nullptr); - - for (;;) - { - void* const new_block = ExReallocatePoolWithTag( - _msize_base(block), size, block, NonPagedPool, __ucxxrt_tag); - if (new_block) - { - return new_block; - } - - // Otherwise, see if we need to call the new handler, and if so call it. - // If the new handler fails, just return nullptr: - if (_query_new_mode() == 0 || !_callnewh(size)) - { - errno = ENOMEM; - return nullptr; - } - - // The new handler was successful; try to allocate again... - } -} diff --git a/src/ucrt/heap/recalloc.cpp b/src/ucrt/heap/recalloc.cpp index d13d300..7f3d4ef 100644 --- a/src/ucrt/heap/recalloc.cpp +++ b/src/ucrt/heap/recalloc.cpp @@ -11,15 +11,20 @@ -// This function provides the logic for the _recalloc() function. It is called -// only in the Release CRT (in the Debug CRT, the debug heap has its own -// implementation of _recalloc()). +// Reallocates a block of memory in the heap. // -// This function must be marked noinline, otherwise recalloc and -// _recalloc_base will have identical COMDATs, and the linker will fold -// them when calling one from the CRT. This is necessary because recalloc -// needs to support users patching in custom implementations. -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _recalloc_base( +// This function reallocates the block pointed to by 'block' such that it is +// 'count * size' bytes in size. The new size may be either greater or less +// than the original size of the block. If the new size is greater than the +// original size, the new bytes are zero-filled. This function shares its +// implementation with the realloc() function; consult the comments of that +// function for more information about the implementation. +// +// This function supports patching and therefore must be marked noinline. +// Both _recalloc_dbg and _recalloc_base must also be marked noinline +// to prevent identical COMDAT folding from substituting calls to _recalloc +// with either other function or vice versa. +extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _recalloc( void* const block, size_t const count, size_t const size @@ -28,10 +33,10 @@ extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _recalloc_base( // Ensure that (count * size) does not overflow _VALIDATE_RETURN_NOEXC(count == 0 || (_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr); - size_t const old_block_size = block != nullptr ? _msize_base(block) : 0; + size_t const old_block_size = block != nullptr ? _msize(block) : 0; size_t const new_block_size = count * size; - void* const new_block = _realloc_base(block, new_block_size); + void* const new_block = realloc(block, new_block_size); // If the reallocation succeeded and the new block is larger, zero-fill the // new bytes: @@ -42,29 +47,3 @@ extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _recalloc_base( return new_block; } - -// Reallocates a block of memory in the heap. -// -// This function reallocates the block pointed to by 'block' such that it is -// 'count * size' bytes in size. The new size may be either greater or less -// than the original size of the block. If the new size is greater than the -// original size, the new bytes are zero-filled. This function shares its -// implementation with the realloc() function; consult the comments of that -// function for more information about the implementation. -// -// This function supports patching and therefore must be marked noinline. -// Both _recalloc_dbg and _recalloc_base must also be marked noinline -// to prevent identical COMDAT folding from substituting calls to _recalloc -// with either other function or vice versa. -extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _recalloc( - void* const block, - size_t const count, - size_t const size - ) -{ -#ifdef _DEBUG - return _recalloc_dbg(block, count, size, _NORMAL_BLOCK, nullptr, 0); -#else - return _recalloc_base(block, count, size); -#endif -} diff --git a/src/ucrt/inc/corecrt_internal.h b/src/ucrt/inc/corecrt_internal.h index 6268986..2ceb6be 100644 --- a/src/ucrt/inc/corecrt_internal.h +++ b/src/ucrt/inc/corecrt_internal.h @@ -194,9 +194,7 @@ extern "C++" // CRT Allocation macros: #define _expand_crt _expand - #define _strdup_crt _strdup - #define _dupenv_s_crt _dupenv_s #define _wdupenv_s_crt _wdupenv_s diff --git a/src/ucrt/internal/per_thread_data.cpp b/src/ucrt/internal/per_thread_data.cpp index 0847249..4f08d24 100644 --- a/src/ucrt/internal/per_thread_data.cpp +++ b/src/ucrt/internal/per_thread_data.cpp @@ -57,8 +57,8 @@ VOID NTAPI __acrt_ptd_table_free( auto ptd = static_cast<__acrt_ptd*>(buffer); if (ptd) { - _free_crt(ptd->_strerror_buffer); - _free_crt(ptd->_wcserror_buffer); + free(ptd->_strerror_buffer); + free(ptd->_wcserror_buffer); } return ExFreeToNPagedLookasideList(&__acrt_startup_ptd_pools, buffer); diff --git a/src/ucrt/startup/onexit.cpp b/src/ucrt/startup/onexit.cpp index 3b4b4ab..808a578 100644 --- a/src/ucrt/startup/onexit.cpp +++ b/src/ucrt/startup/onexit.cpp @@ -213,7 +213,7 @@ extern "C" int __cdecl _execute_onexit_table(_onexit_table_t* const table) if (first != reinterpret_cast<_PVFV*>(-1)) { - _free_crt(first); + free(first); } _PVFV* const encoded_nullptr = __crt_fast_encode_pointer(nullptr); diff --git a/src/ucxxrt.h b/src/ucxxrt.h index 794a251..1d3ba55 100644 --- a/src/ucxxrt.h +++ b/src/ucxxrt.h @@ -41,16 +41,8 @@ #define _VCRTIMP _CRTIMP #endif -#ifdef DBG -# ifndef _DEBUG -# define _DEBUG DBG -# endif -#endif #include -#include -#include - #include @@ -61,6 +53,7 @@ namespace ucxxrt #endif } + #ifndef _ByteSwap16 #define _ByteSwap16(x) ( \ ((uint16_t(x) & uint16_t(0xFF << 8)) >> 8) | \ diff --git a/src/ucxxrt.inl b/src/ucxxrt.inl index 9e58c87..a0c8b14 100644 --- a/src/ucxxrt.inl +++ b/src/ucxxrt.inl @@ -75,12 +75,6 @@ # define NTOS_KERNEL_RUNTIME __KERNEL_MODE #endif -#ifdef DBG -# ifndef _DEBUG -# define _DEBUG DBG -# endif -#endif - #include #include @@ -97,6 +91,10 @@ #include #include +#define _UCXXRT_ALLOCATOR_STDMALLOC 1 +#define _UCXXRT_ALLOCATOR_MINMALLOC 2 +#define _UCXXRT_ALLOCATOR _UCXXRT_ALLOCATOR_STDMALLOC + #include "ucxxrt.h" #if _MSC_VER >= 1200 diff --git a/src/ucxxrtlib.props b/src/ucxxrtlib.props index 377425a..2a3659c 100644 --- a/src/ucxxrtlib.props +++ b/src/ucxxrtlib.props @@ -32,7 +32,7 @@ copy /Y "$(SolutionDir)README.md" "$(SolutionDir)ucxxrt\" copy /Y "$(SolutionDir)LICENSE" "$(SolutionDir)ucxxrt\" copy /Y "$(SolutionDir)src\ucxxrt.props" "$(SolutionDir)ucxxrt\" copy /Y "$(SolutionDir)src\ucxxrt.h" "$(SolutionDir)ucxxrt\" -xcopy /D /S /Y /V /F "$(SolutionDir)inc" "$(SolutionDir)ucxxrt\inc\" +xcopy /D /S /Y /V /F "$(SolutionDir)kext" "$(SolutionDir)ucxxrt\kext\" xcopy /D /S /Y /V /F "$(SolutionDir)lib" "$(SolutionDir)ucxxrt\lib\" /EXCLUDE:$(SolutionDir)src\exclusion.txt