-
Notifications
You must be signed in to change notification settings - Fork 14.9k
tsan: Refine conditions to intercept pthread_cond_t functions #154268
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tsan: Refine conditions to intercept pthread_cond_t functions #154268
Conversation
Created using spr 1.3.5-bogner
@llvm/pr-subscribers-compiler-rt-sanitizer Author: Fangrui Song (MaskRay) ChangesOn glibc x86-64, functions like pthread_cond_init exist in two versions: For newer architectures, such as aarch64 (introduced in glibc 2.17) and Full diff: https://github.com/llvm/llvm-project/pull/154268.diff 1 Files Affected:
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
index e9f8d311bbce1..1e05c00ca85a6 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp
@@ -79,17 +79,6 @@ struct ucontext_t {
};
#endif
-#if defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
- defined(__s390x__)
-#define PTHREAD_ABI_BASE "GLIBC_2.3.2"
-#elif defined(__aarch64__) || SANITIZER_PPC64V2
-#define PTHREAD_ABI_BASE "GLIBC_2.17"
-#elif SANITIZER_LOONGARCH64
-#define PTHREAD_ABI_BASE "GLIBC_2.36"
-#elif SANITIZER_RISCV64
-# define PTHREAD_ABI_BASE "GLIBC_2.27"
-#endif
-
extern "C" int pthread_attr_init(void *attr);
extern "C" int pthread_attr_destroy(void *attr);
DECLARE_REAL(int, pthread_attr_getdetachstate, void *, void *)
@@ -341,11 +330,6 @@ void ScopedInterceptor::DisableIgnoresImpl() {
}
#define TSAN_INTERCEPT(func) INTERCEPT_FUNCTION(func)
-#if SANITIZER_FREEBSD || SANITIZER_NETBSD
-# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func)
-#else
-# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver)
-#endif
#if SANITIZER_FREEBSD
# define TSAN_MAYBE_INTERCEPT_FREEBSD_ALIAS(func) \
INTERCEPT_FUNCTION(_pthread_##func)
@@ -3041,12 +3025,27 @@ void InitializeInterceptors() {
TSAN_INTERCEPT(pthread_timedjoin_np);
#endif
+ // In glibc versions older than 2.36, dlsym(RTLD_NEXT, "pthread_cond_init")
+ // may return an outdated symbol (max(2.2,base_version)) if the port was
+ // introduced before 2.3.2 (when the new pthread_cond_t was introduced).
+#if SANITIZER_GLIBC && !__GLIBC_PREREQ(2, 36) && \
+ (defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \
+ defined(__s390x__))
+# define PTHREAD_ABI_BASE "GLIBC_2.3.2"
TSAN_INTERCEPT_VER(pthread_cond_init, PTHREAD_ABI_BASE);
TSAN_INTERCEPT_VER(pthread_cond_signal, PTHREAD_ABI_BASE);
TSAN_INTERCEPT_VER(pthread_cond_broadcast, PTHREAD_ABI_BASE);
TSAN_INTERCEPT_VER(pthread_cond_wait, PTHREAD_ABI_BASE);
TSAN_INTERCEPT_VER(pthread_cond_timedwait, PTHREAD_ABI_BASE);
TSAN_INTERCEPT_VER(pthread_cond_destroy, PTHREAD_ABI_BASE);
+#else
+ TSAN_INTERCEPT(pthread_cond_init);
+ TSAN_INTERCEPT(pthread_cond_signal);
+ TSAN_INTERCEPT(pthread_cond_broadcast);
+ TSAN_INTERCEPT(pthread_cond_wait);
+ TSAN_INTERCEPT(pthread_cond_timedwait);
+ TSAN_INTERCEPT(pthread_cond_destroy);
+#endif
TSAN_MAYBE_PTHREAD_COND_CLOCKWAIT;
|
#if SANITIZER_FREEBSD || SANITIZER_NETBSD | ||
# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION(func) | ||
#else | ||
# define TSAN_INTERCEPT_VER(func, ver) INTERCEPT_FUNCTION_VER(func, ver) | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can these be deleted? Where else would TSAN_INTERCEPT_VER be defined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TSAN_INTERCEPT_VER
is only used by these pthread_cond_*
functions and is removed as it's no longer used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aren't they still used in lines 3034-3039 of this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. Fixed:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems reasonable to me - I'll follow this pattern in rtsan when it's merged
Created using spr 1.3.5-bogner
// may return an outdated symbol (max(2.2,base_version)) if the port was | ||
// introduced before 2.3.2 (when the new pthread_cond_t was introduced). | ||
#if SANITIZER_GLIBC && !__GLIBC_PREREQ(2, 36) && \ | ||
(defined(__x86_64__) || defined(__mips__) || SANITIZER_PPC64V1 || \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why CPUs make a difference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new pthread_cond symbols were introduced at 2.3.2. If a port (arch) was introduced after 2.3.2, the compatibility symbol (of non-default version) would not compiled, and there will only be one pthread_cond_init
symbol, no need for dlvsym
.
On glibc x86-64, functions like pthread_cond_init exist in two versions: 2.2 (older pthread_cond_t) and 2.3.2 (newer pthread_cond_t). In glibc versions prior to 2.36, using an unversioned interceptor (`dlsym(RTLD_NEXT, "pthread_cond_init")`) retrieves the older 2.2 symbol, which is not desired (https://sourceware.org/bugzilla/show_bug.cgi?id=14932). For newer architectures, such as aarch64 (introduced in glibc 2.17) and riscv64 (introduced in glibc 2.27), a versioned interceptor is unnecessary. Pull Request: llvm/llvm-project#154268
This change broke our musl build:
|
The change in PR #154268 introduced a dependency on the `__GLIBC_PREREQ` macro, which is not defined in musl libc. This caused the build to fail in environments using musl. This patch fixes the build by including `sanitizer_common/sanitizer_glibc_version.h`. This header provides a fallback definition for `__GLIBC_PREREQ` when LLVM is built against non-glibc C libraries, resolving the compilation error.
On glibc x86-64, functions like pthread_cond_init exist in two versions:
2.2 (older pthread_cond_t) and 2.3.2 (newer pthread_cond_t). In glibc
versions prior to 2.36, using an unversioned interceptor
(
dlsym(RTLD_NEXT, "pthread_cond_init")
) retrieves the older 2.2symbol, which is not desired
(https://sourceware.org/bugzilla/show_bug.cgi?id=14932).
For newer architectures, such as aarch64 (introduced in glibc 2.17) and
riscv64 (introduced in glibc 2.27), a versioned interceptor is
unnecessary.