Fix: work-around glibc lying about dlsym()/dlerror() leafness
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 14 Feb 2014 15:02:51 +0000 (10:02 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Fri, 14 Feb 2014 15:02:51 +0000 (10:02 -0500)
Especially in the LTTng-UST malloc instrumentation, we run into the
following situation:

1) Our calloc wrapper is called,
2) we setup the static allocator,
3) we call dlsym() to lookup the symbol of the real allocator,
4) dlsym() calls into calloc(), which is overridden by our own wrapper.
   Our calloc does not see that the static allocator has been set,
   because the stores setting up the static allocator have been optimized
   away by gcc-4.8 (in O2), because the dlsym() prototype declares it
   with the "leaf" attribute, and thus we end up doing an infinite
   recursion, and eventually a segmentation fault.

Thanks to Alexander Monakov for pointing out the culprit of this glibc
bug.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/Makefile.am
include/lttng/ust-dlfcn.h [new file with mode: 0644]
liblttng-ust-dl/ustdl.c
liblttng-ust-fork/ustfork.c
liblttng-ust-libc-wrapper/lttng-ust-malloc.c
liblttng-ust-libc-wrapper/lttng-ust-pthread.c
liblttng-ust/lttng-ust-baddr.c
liblttng-ust/lttng-ust-comm.c

index 4f028dba49b6b11903a7520f53902615130b979a..46cc3fd31213f8765938becafa8aab199881a4c5 100644 (file)
@@ -29,6 +29,7 @@ noinst_HEADERS = \
        ust-comm.h \
        lttng/ust-tid.h \
        lttng/bitfield.h \
+       lttng/ust-dlfcn.h \
        helper.h \
        share.h
 
diff --git a/include/lttng/ust-dlfcn.h b/include/lttng/ust-dlfcn.h
new file mode 100644 (file)
index 0000000..786d3b5
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef _LTTNG_UST_DLFCN_H
+#define _LTTNG_UST_DLFCN_H
+
+/*
+ * lttng/ust-dlfcn.h
+ *
+ * Copyright 2014 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * dlfcn.h compatibility layer.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifdef _DLFCN_H
+#error "Please include lttng/ust-dlfcn.h before dlfcn.h."
+#endif /* _DLFCN_H */
+
+/*
+ * glibc declares dlsym() and dlerror() with __attribute__((leaf)) (see
+ * THROW annotation). Unfortunately, this is not in sync with reality,
+ * as those functions call the memory allocator. Work-around this glibc
+ * bug by declaring our own symbols.
+ *
+ * There has been a similar issue for dlopen() and dlclose(), as
+ * constructors and destructors are called from these functions, so they
+ * are clearly non-leaf. Work-around the issue for those too for older
+ * glibc where these have not been fixed.
+ */
+#define dlopen glibc_dlopen_proto_lies_about_leafness
+#define dlclose glibc_dlclose_proto_lies_about_leafness
+#define dlsym glibc_dlsym_proto_lies_about_leafness
+#define dlerror glibc_dlerror_proto_lies_about_leafness
+#include <dlfcn.h>
+#undef dlerror
+#undef dlsym
+#undef dlclose
+#undef dlopen
+
+extern void *dlopen(__const char *__file, int __mode);
+extern int dlclose(void *__handle) __nonnull ((1));
+extern void *dlsym(void *__restrict __handle,
+               __const char *__restrict __name) __nonnull ((2));
+extern char *dlerror (void);
+
+#endif /* _LTTNG_UST_DLFCN_H */
index ceb9b5bad8115140c03848bb21cf01373cbd02d0..b6abca7b6e13c7562bbb4d1b8fccbcaea64bdf2b 100644 (file)
@@ -18,8 +18,8 @@
 
 #define _LGPL_SOURCE
 #define _GNU_SOURCE
+#include <lttng/ust-dlfcn.h>
 #include <inttypes.h>
-#include <dlfcn.h>
 #include <link.h>
 #include <unistd.h>
 #include <stdio.h>
index 34f674c3c765a13d3dadc3908f765d0caada8d0f..e14296011e8232d23448afd4f1c5839c69cf1446 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #define _GNU_SOURCE
-#include <dlfcn.h>
+#include <lttng/ust-dlfcn.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <signal.h>
index 8296ae29b9e637920b81afc5f75baffa36dae218..54522b4258b69d4d12fbed4ea38b882773d55726 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #define _GNU_SOURCE
-#include <dlfcn.h>
+#include <lttng/ust-dlfcn.h>
 #include <sys/types.h>
 #include <stdio.h>
 #include <assert.h>
index e72b9b40eb357405e601a0b0b69e55c0e5bcbb53..45789aa3463108c72990ad752912309870514a39 100644 (file)
@@ -17,7 +17,7 @@
  */
 
 #define _GNU_SOURCE
-#include <dlfcn.h>
+#include <lttng/ust-dlfcn.h>
 #include <pthread.h>
 
 #define TRACEPOINT_DEFINE
index 90ffe688a3c65ba18c28f54a719f5a33ac235db8..42ae630d99eadd1132025599f13c4505dd697a81 100644 (file)
@@ -18,7 +18,6 @@
 
 #define _LGPL_SOURCE
 #define _GNU_SOURCE
-#include <dlfcn.h>
 #include <link.h>
 
 #include <sys/types.h>
index 27786945b46430e99f5a173ee28a9c7907c6a03c..74d805aefb06c23e42c048498cf2861183d29dfd 100644 (file)
@@ -34,7 +34,6 @@
 #include <time.h>
 #include <assert.h>
 #include <signal.h>
-#include <dlfcn.h>
 #include <urcu/uatomic.h>
 #include <urcu/futex.h>
 #include <urcu/compiler.h>
This page took 0.032996 seconds and 4 git commands to generate.