https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97461
Martin Liška <marxin at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|WAITING |NEW
--- Comment #23 from Martin Liška <marxin at gcc dot gnu.org> ---
Thank you for the testing. Neither of the suggested changes help us.
The core issue is that gcov does not know if it's called from a free/malloc
function.
That said, I see currently 2 possible fixes:
1. help from a malloc library that uses
__gcov_supress_malloc/__gcov_allow_malloc:
commit ee382a226ba0e76e2242dcbb4768033a4809a890
Author: Martin Liska <mli...@suse.cz>
Date: Fri Nov 6 16:59:43 2020 +0100
WIP patch.
diff --git a/libgcc/Makefile.in b/libgcc/Makefile.in
index d6075d32bd4..b235231f9d6 100644
--- a/libgcc/Makefile.in
+++ b/libgcc/Makefile.in
@@ -907,7 +907,7 @@ LIBGCOV_PROFILER = _gcov_interval_profiler
\
LIBGCOV_INTERFACE = _gcov_dump _gcov_fork \
_gcov_execl _gcov_execlp \
_gcov_execle _gcov_execv _gcov_execvp _gcov_execve _gcov_reset \
- _gcov_lock_unlock
+ _gcov_lock_unlock _gcov_supress_malloc _gcov_allow_malloc
LIBGCOV_DRIVER = _gcov
libgcov-merge-objects = $(patsubst %,%$(objext),$(LIBGCOV_MERGE))
diff --git a/libgcc/gcov.h b/libgcc/gcov.h
index 0e3eed31032..444f996692e 100644
--- a/libgcc/gcov.h
+++ b/libgcc/gcov.h
@@ -33,4 +33,12 @@ extern void __gcov_reset (void);
extern void __gcov_dump (void);
+/* Prevent from calling malloc. */
+
+extern void __gcov_supress_malloc (void);
+
+/* Allow calling malloc. */
+
+extern void __gcov_allow_malloc (void);
+
#endif /* GCC_GCOV_H */
diff --git a/libgcc/libgcov-interface.c b/libgcc/libgcov-interface.c
index 3a8a5bf44b8..bcfc38b85c3 100644
--- a/libgcc/libgcov-interface.c
+++ b/libgcc/libgcov-interface.c
@@ -36,6 +36,14 @@ void __gcov_reset (void) {}
void __gcov_dump (void) {}
#endif
+#ifdef L_gcov_supress_malloc
+void __gcov_supress_malloc (void) {}
+#endif
+
+#ifdef L_gcov_allow_malloc
+void __gcov_allow_malloc (void) {}
+#endif
+
#else
extern __gthread_mutex_t __gcov_mx ATTRIBUTE_HIDDEN;
@@ -174,6 +182,20 @@ __gcov_dump (void)
#endif /* L_gcov_dump */
+#ifdef L_gcov_supress_malloc
+void __gcov_supress_malloc (void)
+{
+ __gcov_block_malloc = 1;
+}
+#endif /* L_gcov_supress_malloc */
+
+#ifdef L_gcov_allow_malloc
+void __gcov_allow_malloc (void)
+{
+ __gcov_block_malloc = 0;
+}
+#endif /* L_gcov_block_malloc */
+
#ifdef L_gcov_fork
/* A wrapper for the fork function. We reset counters in the child
so that they are not counted twice. */
diff --git a/libgcc/libgcov-profiler.c b/libgcc/libgcov-profiler.c
index 45ab93c9776..b83b230cd9c 100644
--- a/libgcc/libgcov-profiler.c
+++ b/libgcc/libgcov-profiler.c
@@ -141,6 +141,12 @@ __thread
#endif
struct indirect_call_tuple __gcov_indirect_call;
+// TODO: move to a proper place
+#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
+__thread
+#endif
+int __gcov_block_malloc;
+
/* By default, the C++ compiler will use function addresses in the
vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero
tells the compiler to use function descriptors instead. The value
diff --git a/libgcc/libgcov.h b/libgcc/libgcov.h
index e70cf63b414..2eaed9548ea 100644
--- a/libgcc/libgcov.h
+++ b/libgcc/libgcov.h
@@ -247,6 +247,12 @@ struct indirect_call_tuple
/* Pointer to counters. */
gcov_type *counters;
};
+
+extern
+#if defined(HAVE_CC_TLS) && !defined (USE_EMUTLS)
+__thread
+#endif
+int __gcov_block_malloc;
/* Exactly one of these will be active in the process. */
extern struct gcov_master __gcov_master;
@@ -428,7 +434,12 @@ allocate_gcov_kvp (void)
#endif
if (new_node == NULL)
- new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
+ {
+#if !defined(IN_GCOV_TOOL)
+ if (!__gcov_block_malloc)
+ new_node = (struct gcov_kvp *)xcalloc (1, sizeof (struct gcov_kvp));
+#endif
+ }
return new_node;
}
2) make a dynamic allocation for counters for TOPN at the very beginning in
__gcov_init.
@Honza: What do you think about it?