From 95bc45b63510c7bd329a28b6bff66f0f8fe5866c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Thu, 10 Aug 2023 14:52:18 +0200 Subject: [PATCH] Fix #110971: Replace our own barely-working backtrace on memleaks feature with ASAN utils. Instead of storing the backtrace in all memory blocks, and trying to get meaningful info out of this list of pointers when printing leaked ones, just use `__asan_describe_address` when ASAN is enabled. This also work on Windows, in addition to linux and (presumably) OSX, but does require to build with ASAN enabled. The previous code was not working very well anymore, for some reason the call to `backtrace_symbols` seems to fail to give any meaningful information nowadays on most of Blender code. And it was only implemented for linux and OSX. Based on an idea from @LazyDodo, many thanks! --- .../intern/mallocn_guarded_impl.c | 54 ++----------------- intern/guardedalloc/intern/mallocn_intern.h | 15 ++++++ 2 files changed, 18 insertions(+), 51 deletions(-) diff --git a/intern/guardedalloc/intern/mallocn_guarded_impl.c b/intern/guardedalloc/intern/mallocn_guarded_impl.c index e92ddecf252..3e6bbc2ff57 100644 --- a/intern/guardedalloc/intern/mallocn_guarded_impl.c +++ b/intern/guardedalloc/intern/mallocn_guarded_impl.c @@ -92,24 +92,10 @@ typedef struct MemHead { #ifdef DEBUG_MEMDUPLINAME int need_free_name, pad; #endif - -#ifdef DEBUG_BACKTRACE - void *backtrace[BACKTRACE_SIZE]; - int backtrace_size; -#endif } MemHead; typedef MemHead MemHeadAligned; -#ifdef DEBUG_BACKTRACE -# if defined(__linux__) || defined(__APPLE__) -# include -// Windows is not supported yet. -//# elif defined(_MSV_VER) -//# include -# endif -#endif - typedef struct MemTail { int tag3, pad; } MemTail; @@ -366,38 +352,6 @@ void *MEM_guarded_recallocN_id(void *vmemh, size_t len, const char *str) return newp; } -#ifdef DEBUG_BACKTRACE -# if defined(__linux__) || defined(__APPLE__) -static void make_memhead_backtrace(MemHead *memh) -{ - memh->backtrace_size = backtrace(memh->backtrace, BACKTRACE_SIZE); -} - -static void print_memhead_backtrace(MemHead *memh) -{ - char **strings; - int i; - - strings = backtrace_symbols(memh->backtrace, memh->backtrace_size); - for (i = 0; i < memh->backtrace_size; i++) { - print_error(" %s\n", strings[i]); - } - - free(strings); -} -# else -static void make_memhead_backtrace(MemHead *memh) -{ - (void)memh; /* Ignored. */ -} - -static void print_memhead_backtrace(MemHead *memh) -{ - (void)memh; /* Ignored. */ -} -# endif /* defined(__linux__) || defined(__APPLE__) */ -#endif /* DEBUG_BACKTRACE */ - static void make_memhead_header(MemHead *memh, size_t len, const char *str) { MemTail *memt; @@ -414,10 +368,6 @@ static void make_memhead_header(MemHead *memh, size_t len, const char *str) memh->need_free_name = 0; #endif -#ifdef DEBUG_BACKTRACE - make_memhead_backtrace(memh); -#endif - memt = (MemTail *)(((char *)memh) + sizeof(MemHead) + len); memt->tag3 = MEMTAG3; @@ -769,7 +719,9 @@ static void MEM_guarded_printmemlist_internal(int pydict) (void *)(membl + 1)); #endif #ifdef DEBUG_BACKTRACE - print_memhead_backtrace(membl); +# ifdef WITH_ASAN + __asan_describe_address(membl); +# endif #endif } if (membl->next) { diff --git a/intern/guardedalloc/intern/mallocn_intern.h b/intern/guardedalloc/intern/mallocn_intern.h index 3f048a558a8..6ed97f6d264 100644 --- a/intern/guardedalloc/intern/mallocn_intern.h +++ b/intern/guardedalloc/intern/mallocn_intern.h @@ -72,6 +72,21 @@ size_t malloc_usable_size(void *ptr); # define MEM_INLINE static inline #endif +/* BEGIN copied from BLI_asan.h */ + +/* Clang defines this. */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif + +#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) && \ + (!defined(_MSC_VER) || _MSC_VER > 1929) /* MSVC 2019 and below doesn't ship ASAN headers. */ +# include "sanitizer/asan_interface.h" +# define WITH_ASAN +#endif + +/* END copied from BLI_asan.h */ + #define IS_POW2(a) (((a) & ((a)-1)) == 0) /* Extra padding which needs to be applied on MemHead to make it aligned. */ -- 2.30.2