This is a repeat of GNATS libc/1188 issue from 13 years ago:
I accept that there is ambiguity in what dlsym(..., "foo") is ambiguous, but shouldn't two dlsym()s below return the *same* answer?
void *p = dlsym(RTLD_NEXT, "fopen");
void *h = dlopen("libc.so.6", RTLD_LAZY);
void *q = dlsym(h, "fopen");
printf("%p -- p (via RTLD_NEXT)\n", p);
printf("%p -- q (via dlsym(%p))\n", q, h);
gcc -m32 -g t.c -ldl && ./a.out
0xf76e41a0 -- p (via RTLD_NEXT)
0xf7634e70 -- q (via dlsym(0xf7758c88))
Google ref: b/7695672
Worse is that dlsym for a symbol that has no default returns NULL, for example in the case of libpthread.so and you must then use dlvsym to get the symbol.
I agree this should be fixed and dlsym should behave like the application would normally behave had it just been compiled. You get the default version of the symbol and RTLD_NEXT gives you the next version and so on.
*** Bug 20220 has been marked as a duplicate of this bug. ***
I just saw a compiler-rt patch which wants to change a dlsym call to dlvsym because of this: https://reviews.llvm.org/D96348
> COMMON_INTERCEPT_FUNCTION_GLIBC_VER(regexec, "GLIBC_2.3.4");
Due to how the code is organized (it is difficult to inspect the default version name when compiling), compiler-rt will need to be follow glibc default version names more closely, which is undesired.