Add memory tracking and sanitization hooks

Intended use is sanitization of BoringSSL allocations.

Change-Id: Ia577f944d19e5b0b77373fedd0970e2c0c97cd21
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/39824
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/mem.c b/crypto/mem.c
index a864a66..121a736 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -85,6 +85,13 @@
 // Windows will emit strong symbols instead. See
 // https://bugs.llvm.org/show_bug.cgi?id=37598
 #if defined(__GNUC__) || (defined(__clang__) && !defined(_MSC_VER))
+#define WEAK_SYMBOL_DECL
+#define WEAK_SYMBOL_DEFAULT_IMPL __attribute((weak, noinline))
+#else
+#define WEAK_SYMBOL_DECL static
+#define WEAK_SYMBOL_DEFAULT_IMPL static
+#endif
+
 // sdallocx is a sized |free| function. By passing the size (which we happen to
 // always know in BoringSSL), the malloc implementation can save work. We cannot
 // depend on |sdallocx| being available so we declare a wrapper that falls back
@@ -94,16 +101,22 @@
 // implementation is statically linked with BoringSSL. So, if |sdallocx| is
 // provided in, say, libc.so, we still won't use it because that's dynamically
 // linked. This isn't an ideal result, but its helps in some cases.
-void sdallocx(void *ptr, size_t size, int flags);
-
-__attribute((weak, noinline))
-#else
-static
-#endif
-void sdallocx(void *ptr, size_t size, int flags) {
+WEAK_SYMBOL_DECL void sdallocx(void *ptr, size_t size, int flags);
+WEAK_SYMBOL_DEFAULT_IMPL void sdallocx(void *ptr, size_t size, int flags) {
   free(ptr);
 }
 
+// The following two functions are for memory tracking. They are no-ops by
+// default but can be overridden at link time if the application needs to
+// observe heap operations.
+WEAK_SYMBOL_DECL void OPENSSL_track_memory_alloc(void *ptr, size_t size);
+WEAK_SYMBOL_DEFAULT_IMPL void OPENSSL_track_memory_alloc(void *ptr,
+                                                         size_t size) {}
+
+WEAK_SYMBOL_DECL void OPENSSL_track_memory_free(void *ptr, size_t size);
+WEAK_SYMBOL_DEFAULT_IMPL void OPENSSL_track_memory_free(void *ptr,
+                                                        size_t size) {}
+
 void *OPENSSL_malloc(size_t size) {
   if (size + OPENSSL_MALLOC_PREFIX < size) {
     return NULL;
@@ -117,6 +130,7 @@
   *(size_t *)ptr = size;
 
   __asan_poison_memory_region(ptr, OPENSSL_MALLOC_PREFIX);
+  OPENSSL_track_memory_alloc(ptr, size + OPENSSL_MALLOC_PREFIX);
   return ((uint8_t *)ptr) + OPENSSL_MALLOC_PREFIX;
 }
 
@@ -129,6 +143,7 @@
   __asan_unpoison_memory_region(ptr, OPENSSL_MALLOC_PREFIX);
 
   size_t size = *(size_t *)ptr;
+  OPENSSL_track_memory_free(ptr, size + OPENSSL_MALLOC_PREFIX);
   OPENSSL_cleanse(ptr, size + OPENSSL_MALLOC_PREFIX);
   sdallocx(ptr, size + OPENSSL_MALLOC_PREFIX, 0 /* flags */);
 }