vgpreload_core-arm-linux.so from valgrind-3.13.0-6.fc27.armv7hl demands that the symbol __libc_freeres exist [typically found in GNU libc.so.6], which prevents that particular valgrind from checking apps whose libraries do not have such a symbol, such as the libraries used by Android. Many Android apps run just fine on Linux (using the Android runtime linker, libc, libm, libdl, etc.), and valgrind should be able to check them. The complaint from one Android app is: libc: CANNOT LINK EXECUTABLE "./my_app": cannot locate symbol "__libc_freeres" referenced by "/usr/lib/valgrind/vgpreload_core-arm-inux.so"... So, do not reference __libc_freeres directly. Make it a Weak reference (check the pointer value; if 0 then do not use it), or do an explicit lookup equivalent to dlsym(handle, "__libc_freeres"). ===== readelf --relocs /usr/lib/valgrind/vgpreload_core-arm-linux.so Relocation section '.rel.plt' at offset 0x3d0 contains 4 entries: Offset Info Type Sym.Value Sym. Name 0001100c 00000316 R_ARM_JUMP_SLOT 00000000 __cxa_finalize 00011010 00000416 R_ARM_JUMP_SLOT 00000000 _ZN9__gnu_cxx9__freere 00011014 00000616 R_ARM_JUMP_SLOT 00000000 __libc_freeres 00011018 00000816 R_ARM_JUMP_SLOT 00000000 __gmon_start__ =====
If __libc_freeres is used by some library function that is invoked by vgpreload_core-arm-linux.so then vgpreload should implement such a function itself, with an implementation that does the explicit lookup and forwarding if found.
Calling optional __gnu_cxx::__freeres() already leverages weak reference mechanism. So __libc__freeres() could use the same mechanism. After you make __libc_freeres() optional, please delete references to it in README_DEVELOPERS as it would be no longer needed.
I hit this again today using valgrind-3.15.0 when the default libc on the target platform is glibc-2.29-12.fc30.aarch64 but the actual libc in the target application is from Android 28. __libc_freeres is not defined for all target app environments; therefore __libc_freeres MUST be a WEAK symbol!
See comment #2. This could be done the same way as is done for __gnu_cxx::__freeres().
This looks fairly straightforward. Just change # if defined(VGO_linux) /* __libc_freeres() not yet available on Solaris. */ extern void __libc_freeres(void); if ((to_run & VG_RUN__LIBC_FREERES) != 0) { __libc_freeres(); } # endif to extern void __libc_freeres(void) __attribute__((weak)); if (((to_run & VG_RUN__LIBC_FREERES) != 0)) && (__libc_freeres != NULL)) { __libc_freeres(); } in vg_preloaded.c
Created attachment 133107 [details] Patch as per discussion
(In reply to Paul Floyd from comment #6) > Created attachment 133107 [details] > Patch as per discussion Looks correct to me. But I don't have any non-glibc system around to test it.
(In reply to Mark Wielaard from comment #7) > Looks correct to me. > But I don't have any non-glibc system around to test it. Regtests are OK on Solaris and FreeBSD. However I don't have any non-libc Linux systems to test. John, could you test this patch?
Yes, the patch works, just like the handling of __gnu_cxx::__freeres(). Tested on armv7hl.
commit 35c9c33897ef89b08e1518ed16244e70bc6996da Author: Paul Floyd <pjfloyd@wanadoo.fr> Date: Mon Nov 9 16:31:40 2020 +0100 Bug 384729 - __libc_freeres inhibits cross-platform valgrind