From d5dd35c73988da3ff7500cc8aba55509275284da Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Wed, 23 Dec 2020 12:03:06 -0600 Subject: [PATCH] add --enable-trackmemory=verbose, and add WOLFSSL_TEST_MAX_RELATIVE_HEAP_{BYTES,ALLOCS} and -m/-a (runtime counterparts) to wolfcrypt_test(). also add -h to wolfcrypt_test() to print available options. --- configure.ac | 12 ++++-- wolfcrypt/src/wc_port.c | 13 ++++++ wolfcrypt/test/test.c | 76 ++++++++++++++++++++++++++++++++--- wolfssl/test.h | 6 +-- wolfssl/wolfcrypt/mem_track.h | 28 +++++++++++-- wolfssl/wolfcrypt/wc_port.h | 5 +++ 6 files changed, 124 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 8ab179faf..2b0e4d7b9 100644 --- a/configure.ac +++ b/configure.ac @@ -2228,7 +2228,6 @@ then AC_MSG_ERROR(stacksize-verbose needs thread-local storage.) fi AM_CFLAGS="$AM_CFLAGS -DHAVE_STACK_SIZE_VERBOSE" - ENABLED_STACKSIZE=yes fi @@ -2259,7 +2258,7 @@ AC_ARG_ENABLE([trackmemory], [ ENABLED_TRACKMEMORY=no ] ) -if test "$ENABLED_TRACKMEMORY" = "yes" +if test "$ENABLED_TRACKMEMORY" != "no" then if test "$ENABLED_MEMORY" = "yes" then @@ -2267,6 +2266,10 @@ then else AC_MSG_ERROR([trackmemory requires using wolfSSL memory (--enable-memory).]) fi + if test "$ENABLED_TRACKMEMORY" = "verbose" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TRACK_MEMORY_VERBOSE" + fi fi # MEMORY usage logging @@ -5927,7 +5930,7 @@ if test "x$ENABLED_LINUXKM" = "xyes"; then if test "$ENABLED_SP_MATH" = "no" && test "$ENABLED_SP_MATH_ALL" = "no"; then AC_MSG_ERROR([--enable-sp-math or --enable-sp-math-all is required for --enable-linuxkm.]) fi - if test "$ENABLED_STACKSIZE" = "yes"; then + if test "$ENABLED_STACKSIZE" != "no"; then AC_MSG_ERROR([--enable-stacksize is incompatible with --enable-linuxkm.]) fi if test "$ENABLED_STACKLOG" = "yes"; then @@ -6062,7 +6065,7 @@ AM_CONDITIONAL([BUILD_NO_LIBRARY],[test "$ENABLED_NO_LIBRARY" = "yes"]) AM_CONDITIONAL([BUILD_RC2],[test "x$ENABLED_RC2" = "xyes"]) if test "$ax_enable_debug" = "yes" || - test "$ENABLED_STACKSIZE" = "yes" || + test "$ENABLED_STACKSIZE" != "no" || (test "$ENABLED_LEANTLS" = "no" && test "$ENABLED_LEANPSK" = "no" && test "$ENABLED_LOWRESOURCE" = "no") @@ -6360,6 +6363,7 @@ echo " * LIBZ: $ENABLED_LIBZ" echo " * Examples: $ENABLED_EXAMPLES" echo " * Crypt tests: $ENABLED_CRYPT_TESTS" echo " * Stack sizes in tests: $ENABLED_STACKSIZE" +echo " * Heap stats in tests: $ENABLED_TRACKMEMORY" echo " * User Crypto: $ENABLED_USER_CRYPTO" echo " * Fast RSA: $ENABLED_FAST_RSA" echo " * Single Precision: $ENABLED_SP" diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 9538cacb3..ac6487d54 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -290,6 +290,19 @@ int wolfCrypt_Init(void) return ret; } +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE +long wolfCrypt_heap_peakAllocs_checkpoint(void) { + long ret = ourMemStats.peakAllocsTripOdometer; + ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - + ourMemStats.totalDeallocs; + return ret; +} +long wolfCrypt_heap_peakBytes_checkpoint(void) { + long ret = ourMemStats.peakBytesTripOdometer; + ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; + return ret; +} +#endif /* return success value is the same as wolfCrypt_Init */ int wolfCrypt_Cleanup(void) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 11377cccf..4175c95b0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -55,6 +55,35 @@ #define STACK_SIZE_INIT() #endif +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE +#ifdef WOLFSSL_TEST_MAX_RELATIVE_HEAP_ALLOCS + static ssize_t max_relative_heap_allocs = WOLFSSL_TEST_MAX_RELATIVE_HEAP_ALLOCS; +#else + static ssize_t max_relative_heap_allocs = -1; +#endif +#ifdef WOLFSSL_TEST_MAX_RELATIVE_HEAP_BYTES + static ssize_t max_relative_heap_bytes = WOLFSSL_TEST_MAX_RELATIVE_HEAP_BYTES; +#else + static ssize_t max_relative_heap_bytes = -1; +#endif +#define PRINT_HEAP_CHECKPOINT() { \ + const ssize_t _rha = wolfCrypt_heap_peakAllocs_checkpoint() - heap_baselineAllocs; \ + const ssize_t _rhb = wolfCrypt_heap_peakBytes_checkpoint() - heap_baselineBytes; \ + printf(" relative heap peak usage: %ld alloc%s, %ld bytes\n", \ + _rha, \ + _rha == 1 ? "" : "s", \ + _rhb); \ + if ((max_relative_heap_allocs > 0) && (_rha > max_relative_heap_allocs)) \ + return err_sys("heap allocs exceed designated max.", -1); \ + if ((max_relative_heap_bytes > 0) && (_rhb > max_relative_heap_bytes)) \ + return err_sys("heap bytes exceed designated max.", -1); \ + heap_baselineAllocs = wolfCrypt_heap_peakAllocs_checkpoint(); \ + heap_baselineBytes = wolfCrypt_heap_peakBytes_checkpoint(); \ + } +#else +#define PRINT_HEAP_CHECKPOINT() +#endif + #ifdef __GNUC__ _Pragma("GCC diagnostic ignored \"-Wunused-function\""); #endif @@ -477,11 +506,11 @@ static int err_sys(const char* msg, int es) #ifdef WOLFSSL_LINUXKM lkm_printf("%s error = %d\n", msg, es); + EXIT_TEST(es); #else printf("%s error = %d\n", msg, es); -#endif - EXIT_TEST(-1); +#endif } #ifndef HAVE_WOLFCRYPT_TEST_OPTIONS @@ -547,11 +576,18 @@ static int wolfssl_pb_print(const char* msg, ...) va_start(args, fmt); STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK(max_relative_stack, vprintf(fmt, args)); va_end(args); + PRINT_HEAP_CHECKPOINT(); TEST_SLEEP(); } #else /* redirect to printf */ - #define test_pass(...) { if (STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK(max_relative_stack, printf(__VA_ARGS__)) < 0) { return err_sys("post-test check failed", -1); }} + #define test_pass(...) { \ + if (STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK \ + (max_relative_stack, printf(__VA_ARGS__)) < 0) { \ + return err_sys("post-test check failed", -1); \ + } \ + PRINT_HEAP_CHECKPOINT(); \ + } /* stub the sleep macro */ #define TEST_SLEEP() #endif @@ -563,8 +599,18 @@ int wolfcrypt_test(void* args) #endif { int ret; +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + long heap_baselineAllocs, heap_baselineBytes; +#endif STACK_SIZE_INIT(); +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + (void)wolfCrypt_heap_peakAllocs_checkpoint(); + heap_baselineAllocs = wolfCrypt_heap_peakAllocs_checkpoint(); + (void)wolfCrypt_heap_peakBytes_checkpoint(); + heap_baselineBytes = wolfCrypt_heap_peakBytes_checkpoint(); +#endif + printf("------------------------------------------------------------------------------\n"); printf(" wolfSSL version %s\n", LIBWOLFSSL_VERSION_STRING); printf("------------------------------------------------------------------------------\n"); @@ -575,17 +621,35 @@ int wolfcrypt_test(void* args) #endif ((func_args*)args)->return_code = -1; /* error state */ #ifdef HAVE_WOLFCRYPT_TEST_OPTIONS - while ((ch = mygetopt(((func_args*)args)->argc, ((func_args*)args)->argv, "s:")) != -1) { + while ((ch = mygetopt(((func_args*)args)->argc, ((func_args*)args)->argv, "s:m:a:h")) != -1) { switch(ch) { case 's': #ifdef HAVE_STACK_SIZE_VERBOSE max_relative_stack = (ssize_t)atoi(myoptarg); break; #else - return err_sys("-s (max relative stack size) requires HAVE_STACK_SIZE_VERBOSE.", -1); + return err_sys("-s (max relative stack bytes) requires HAVE_STACK_SIZE_VERBOSE (--enable-stacksize=verbose).", -1); #endif + case 'm': +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + max_relative_heap_bytes = (ssize_t)atoi(myoptarg); + break; +#else + return err_sys("-m (max relative heap memory bytes) requires WOLFSSL_TRACK_MEMORY_VERBOSE (--enable-trackmemory=verbose).", -1); +#endif + case 'a': +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + max_relative_heap_allocs = (ssize_t)atoi(myoptarg); + break; +#else + return err_sys("-a (max relative heap allocs) requires WOLFSSL_TRACK_MEMORY_VERBOSE (--enable-trackmemory=verbose).", -1); +#endif + case 'h': + return err_sys("\ +options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ + [-a max_relative_heap_allocs] [-h]\n", 0); default: - return err_sys("unknown test option.", -1); + return err_sys("unknown test option. try -h.", -1); } } #endif diff --git a/wolfssl/test.h b/wolfssl/test.h index b3a83491a..5518f8ad5 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -2126,7 +2126,7 @@ int StackSizeHWMReset(void) #define STACK_SIZE_CHECKPOINT(...) ({ \ ssize_t HWM = StackSizeHWM_OffsetCorrected(); \ __VA_ARGS__; \ - printf("relative stack used = %ld\n", HWM); \ + printf(" relative stack peak usage = %ld bytes\n", HWM); \ StackSizeHWMReset(); \ }) @@ -2134,10 +2134,10 @@ int StackSizeHWMReset(void) ssize_t HWM = StackSizeHWM_OffsetCorrected(); \ int _ret; \ __VA_ARGS__; \ - printf("relative stack used = %ld\n", HWM); \ + printf(" relative stack peak usage = %ld bytes\n", HWM); \ _ret = StackSizeHWMReset(); \ if ((max >= 0) && (HWM > (ssize_t)(max))) { \ - printf("relative stack usage at %s L%d exceeds designated max %ld.\n", __FILE__, __LINE__, (ssize_t)(max)); \ + printf(" relative stack usage at %s L%d exceeds designated max %ld bytes.\n", __FILE__, __LINE__, (ssize_t)(max)); \ _ret = -1; \ } \ _ret; \ diff --git a/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index d33e90e60..1d5ade9d4 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/wolfssl/wolfcrypt/mem_track.h @@ -76,6 +76,15 @@ long totalBytes; /* total number of bytes allocated */ long peakBytes; /* concurrent max bytes */ long currentBytes; /* total current bytes in use */ +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + long peakAllocsTripOdometer; /* peak number of concurrent allocations, + * subject to reset by + * wolfCrypt_heap_peak_checkpoint() + */ + long peakBytesTripOdometer; /* peak concurrent bytes, subject to reset + * by wolfCrypt_heap_peak_checkpoint() + */ +#endif } memoryStats; typedef struct memHint { @@ -170,8 +179,17 @@ ourMemStats.totalAllocs++; ourMemStats.totalBytes += sz; ourMemStats.currentBytes += sz; - if (ourMemStats.currentBytes > ourMemStats.peakBytes) - ourMemStats.peakBytes = ourMemStats.currentBytes; + #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + if (ourMemStats.peakAllocsTripOdometer < ourMemStats.totalAllocs - ourMemStats.totalDeallocs) + ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - ourMemStats.totalDeallocs; + if (ourMemStats.peakBytesTripOdometer < ourMemStats.currentBytes) { + ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; + #endif + if (ourMemStats.currentBytes > ourMemStats.peakBytes) + ourMemStats.peakBytes = ourMemStats.currentBytes; + #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + } + #endif #endif #ifdef DO_MEM_LIST if (pthread_mutex_lock(&memLock) == 0) { @@ -338,8 +356,12 @@ ourMemStats.totalBytes = 0; ourMemStats.peakBytes = 0; ourMemStats.currentBytes = 0; +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + ourMemStats.peakAllocsTripOdometer = 0; + ourMemStats.peakBytesTripOdometer = 0; +#endif #endif - + #ifdef DO_MEM_LIST XMEMSET(&ourMemList, 0, sizeof(ourMemList)); diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index da89676bf..fa36b0d83 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -449,6 +449,11 @@ WOLFSSL_API int wc_SetMutexCb(mutex_cb* cb); WOLFSSL_API int wolfCrypt_Init(void); WOLFSSL_API int wolfCrypt_Cleanup(void); +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + WOLFSSL_API long wolfCrypt_heap_peakAllocs_checkpoint(void); + WOLFSSL_API long wolfCrypt_heap_peakBytes_checkpoint(void); +#endif + /* FILESYSTEM SECTION */ /* filesystem abstraction layer, used by ssl.c */