<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/59820>59820</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [sanitizer,glibc>=2.36] program preloading pthread_mutex_lock does not play well with __pthread_mutex_lock interceptor
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          MaskRay
      </td>
    </tr>
</table>

<pre>
    https://reviews.llvm.org/D46793 implemented sanitizer interceptors `__pthread_mutex_lock` and `__pthread_mutex_unlock`.
My understanding is that this is to support some applications using the two symbols with tsan. Other sanitizers don't need the two interceptors.

rr-debugger/rr has a preload shared object intercepting `pthread_mutex_lock` (https://github.com/rr-debugger/rr/issues/2329).
(ClickHouse seems to do so as well (https://github.com/ClickHouse/ClickHouse/pull/44811))
This means that sanitizers' `__pthread_mutex_lock` interceptor cannot call `pthread_mutex_lock` returned by `dlsym(RTLD_NEXT,...)` (infinite loop).
So the current code calls `__pthread_mutex_lock`, which only has a non-default version in glibc.

```
% nm -D libc.so | grep pthread_mutex_lock
00000000000df540 T __pthread_mutex_lock@GLIBC_2.2.5
00000000000df540 T pthread_mutex_lock@@GLIBC_2.2.5
```

(https://maskray.me/blog/2022-05-29-glibc#buildabi-versions.h)
On x86_64, the version `GLIBC_2.2.5` is decided by glibc `sysdeps/unix/sysv/linux/x86_64/64/shlib-versions`. Other ports may have a different version.

---

In glibc 2.36, my https://sourceware.org/git/?p=glibc.git;a=commit;h=efa7936e4c91b1c260d03614bb26858fbb8a0204 fixed a long-term `RTLD_NEXT` mismatch with `RTLD_DEFAULT`
(this mismatch bug led to many versioned interceptors which were otherwise not needed).

```c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

int main() {
  printf("pthread_mutex_lock: %p (via RTLD_DEFAULT)\n", dlsym(RTLD_DEFAULT, "pthread_mutex_lock"));
 printf("pthread_mutex_lock: %p (via RTLD_NEXT)\n", dlsym(RTLD_NEXT, "pthread_mutex_lock"));
  printf("__pthread_mutex_lock: %p (via RTLD_DEFAULT)\n", dlsym(RTLD_DEFAULT, "__pthread_mutex_lock"));
 printf("__pthread_mutex_lock: %p (via RTLD_NEXT)\n", dlsym(RTLD_NEXT, "__pthread_mutex_lock"));
}
```

```
% ./with-glibc-2.35
pthread_mutex_lock: 0x7fdc5cc8aaa0 (via RTLD_DEFAULT)
pthread_mutex_lock: 0x7fdc5cc8aaa0 (via RTLD_NEXT)
__pthread_mutex_lock: (nil) (via RTLD_DEFAULT)
__pthread_mutex_lock: 0x7fdc5cc8aaa0 (via RTLD_NEXT)
% ./with-glibc-2.36
pthread_mutex_lock: 0x7fb2d1d1e540 (via RTLD_DEFAULT)
pthread_mutex_lock: 0x7fb2d1d1e540 (via RTLD_NEXT)
__pthread_mutex_lock: (nil) (via RTLD_DEFAULT)
__pthread_mutex_lock: (nil) (via RTLD_NEXT)
```

As a side effect, this change adds complexity when sanitizers need to wrap a non-default version definition.
We need to know the version name for every sanitizer-supported architecture, then call `dlsym(RTLD_NEXT, ...)`.
An alternative is to get a hangle for libc.so.6, then call `dlsym(handle, "pthread_mutex_lock")`.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8V9-PozgS_mucl1IQMYHAQx56ksneSrM70myP7t4iYxfB28ZGtul07q8_GcivXdLTGp221SICu1yfvyp_rmLOyYNGXJP0E0m3M9b52tj1b8y9fGOnWWnEaV173zqSPBG6I3Rn8VXi0UVKvTaRsQdCd9tltioSkE2rsEHtUYBjWnr5X7QgtUfLsfXGOiBZvN-3vrbIxL7pPL7tleEvJIuBaTE13OlxQkTiLYmffjtBpwVa55kWUh9AOvA18-Br6foXA65rW2M9ONMgsLZVkjMvjXbQuWDiawR_NOBOTWmUg6P0NXjHdARffY32it6BMJrQlQeNKC6Gt3sacQ1Pa-cCy-5wQBuoslAzBwxai8owAa5mFgWY8k_k_rpKwESyeJoXQvP7ABykr7sy4qbpXdw7JHQnnevQEbqjCS0ILc4Aab5Rkr_8y3QOwSE2PVfCgDPAHBxRqR84u9r_9aXtlCJ0t1zmiwXpvQ5On0NQGmR6DNKVWEJX72XDDcPAmdbGA2cB4COaLPrOahRQnsIkodypITT_9vxlu__983-eCd1EURSADZxKXUktPYIypr2y9Ifpg8w7a1F74EZg7_i91CV0A8da8hqMVqcx5NroucCKdcrDK1onjQap4aBkye9SJiww_I9hSkE3MN9CP9MZIKsNHCy2MOG8N4mvf6JKlzE8wyTSZfzLl18_bfY0olH60HTScMr2r8DPWXafQA1zL5adoiakSalM0AsaUzqP0zkt5j0fhCZlJ5VgpZyPXLmoviTRVw1vebbPloHoEJ0znyS7QxXSxoFALsWQB_3iYZY7OYFtOBOdlm-E7tzJvRK6U1J34fW8_K5_uFrJ8gIkSM8oC0FUHDQsxPgVgYGQVYV9ooyz7yI7n89vX38dow80SrKwleYE91w501mOR2ZxFNaD9GEk2bUk2Q6pEz4lnxhJttw0Tf9Sk2SLFVsVSYZLXizKBadZLOIkWyzLkmZ5mldlmbOYxkuo5BsKYKCMPsw92ibwcz0lWQyNdA3zvB5k8Ty6_bx7-v7l-SZP815xL7PL7gAqaKSBhunTmREU9zfAcFCOaBFMIPUoHUI43kFgUdzo1X2S8bPbRGAlNcL-l9-_7__4-v3b5vNlSGquOoFAko1QFddRTZLJUeeFNLej_VNqDw2TmtCc0ALI6tPwHaC1Uvuq_04nDkjyBISmbdCVV8ngjjBakHSjCaUh5HeydJmxgellg02vpckZyE_gGMTvIYhRGz-M4A7CpMz8P8iYXPh9Oj6M5eOEfAwFWW3fE8S_y3tE6C6crUH85jRKRkWd3kD8tqoETznPGWPxI1p_boEzF731YwZzLVV_It7x_cj6o96nmcl-tLGSioVYYLi7fo6ZBwv8A8xMW9-TMpVST6G-cFIgYFUh98O1KB3wmukDAhPCATehGn-T_gTHGvVtSTuUsgaOlrUPKpVeY6W_3mj_xovZizbHu2tYswahMhbwFe3p6mk-1uHhvrG8lh657yyOt7i-FHSTx-9SrI0AnjQw5dFq5uUrjoX-AT0wCLtWA4KxZoqyh05qpoXCHyleFkczsU5EkRRshutFtqJ5XBRxPqvXFKs0TXmWU5ZkVYkLkXG2XOWrqqgQ2WIm1zSmSbyIl3FK0ziPFlm5KkpkCfKiwEyQZYwNk-rSQ836mn2dFjmNZ4qVqFzfkFGq8Qj9YACWbmd2HWzmZXdwZBkr6fy1E5t56VXfyV1CQOhmqLCSzyTZ9ucp3UJrzcGy5tyWhPbj70yAMOj6m7lV7DS0B31FMJXOt3f8rLNq_U4XEeCOP_PWmj_7DL52LT0J_wsAAP__hIKWnA">