valgrind-macos icon indicating copy to clipboard operation
valgrind-macos copied to clipboard

Question: What is [shared pmap]? / False positive?

Open real-or-random opened this issue 8 months ago • 1 comments

I guess this is more of a question than an issue. The following is from the failure was trying to debug (now with a useful stack strace after #125 merged!):

==22464== Conditional jump or move depends on uninitialised value(s)
==22464==    at 0x7FF801C18587: ??? (in /dev/macos/internals/[shared pmap])
==22464==    by 0x100000690: label_lookup (silentpayments.c:104)
==22464==    by 0x1000217D8: secp256k1_silentpayments_recipient_scan_outputs (main_impl.h:575)
==22464==    by 0x100000C4D: main (silentpayments.c:386)
==22464==  Uninitialised value was created by a stack allocation
==22464==    at 0x100020ACD: secp256k1_silentpayments_recipient_scan_outputs (main_impl.h:477)

This line of code in label_lookup is a call to memcmp (which, I assume from the above, has been optimized by the compiler?). I know _internal_memcmp is redirect but it does not appear here.

I tried VALGRIND_CHECK_MEM_IS_DEFINED and it confirms that all bytes in both arguments of the call are defined. So this looks like a false positive?! But to be honest, I have no idea what [shared pmap] is? I'd appreciate any ideas or pointers, but also feel free to close this as not really actionable (unless we want to add a suppression?)

real-or-random avatar Mar 25 '25 10:03 real-or-random

This is a bit of a complex one because a lot of things are coming together at the same time.

What is /dev/macos/internals/[shared pmap]?

As part of the work for arm64, I needed a lot of debugging information, so I tried to get as much data out of macOS as I could. This path is a fake path introduced as part of this for memory regions without any name. In previous versions of Valgrind, you would just see

==22464==    at 0x7FF801C18587: ??? (in ???)

This name is determined through the kernel's mach_vm_region_recurse API. This is the same thing vmmap does when you run it against a binary and it says something like MALLOC guard page. You can find all potential paths and their vm tag equivalent here: https://github.com/LouisBrunner/valgrind-macos/blob/5d88e076ea4b2601a2788214c9ea5a51f1dbe136/coregrind/m_aspacemgr/aspacemgr-linux.c#L3805

But what does it actually mean? From the context and your expectations of memcmp, it is the part of the memory where the DYLD cache is loaded by the kernel.

Why does this show an error?

At start, we load a few dyld explicitly to ensure important symbols (especially for malloc) are loaded by Valgrind, the rest are loaded by the client binary itself. This is important because Valgrind relies on symbol names to replace calls to a lot of functions (called redirections internally).

As many of those core libc functions (like memcmp) rely on intrinsics and other vectorized tricks for performance (I am not super familiar with the details), they do tend to show a lot of false positives (as they seemingly load memory that's not been initialized).

Unfortunately, it seems that the symbol is not loaded at all. This is usually an issue with the symbol itself being missing from DYLD cache, or it could be a Valgrind bug. Otherwise, memcmp would be replaced by the Valgrind version.

How do we fix this?

If you are positive that the memory is defined, then it's most likely a false positive from the optimized code from the system memcmp.

Which architecture/macOS version is this? I know you have been running Valgrind on amd64 without issue for a while, so if this is happening on there, then it seems like it would a regression, potentially from the (unfortunately extensive) arm64 changes. If this is arm64, then it's a symbol loading issue or potentially a new entrypoint into memcmp that Valgrind isn't expecting.

LouisBrunner avatar Mar 25 '25 11:03 LouisBrunner

Sorry for being silent here for months. This explanation is great!

I know you have been running Valgrind on amd64 without issue for a while, so if this is happening on there, then it seems like it would a regression, potentially from the (unfortunately extensive) arm64 changes.

This is on amd64 and on macOS 13. We currently don't have any call to memcmp in our code base, and we see the failure only in new code currently proposed in two PRs. So nothing on our side indicates that it's a regression in valgrind-macos (though it could still be the case, of course).

The background is that we banned memcmp a while ago in an abundance of caution after gcc's implementation of _builtin_memcpy had a rather scary bug. We currently use a naive self-implemented version of memcmp to avoid this gcc bug. (This may be questionable but it's the state of affairs.) The two PRs introduce calls to the real memcmp in example code we ship as documentation.

Given we see this in a second PR, I really suspect that this is a false positive, and it may be worth producing a minimal example.

real-or-random avatar Aug 04 '25 08:08 real-or-random

Here's a rather minimal test case (recovery.c):

#include <string.h>

int main(void) {
    unsigned char buf1[33];
    unsigned char buf2[33];

    memset(buf1, 5, 33);
    memset(buf2, 5, 33);
    memcmp(buf1, buf2, 33);

    return 0;
}

Compile this using Apple clang version 15.0.0 (clang-1500.1.0.2.5) with flags:

clang -O2  -std=c89 -pedantic -Wno-long-long -Wnested-externs -Wshadow -Wstrict-prototypes -Wundef -Wno-overlength-strings -Wall -Wno-unused-function -Wextra -Wcast-align -Wconditional-uninitialized -Wreserved-identifier -Werror -pedantic-errors -fno-builtin-memcmp -gdwarf-4

The only relevant flag is probably -fno-builtin-memcmp, which is used to stop clang from optimizing essentially the entire program away.

valgrind --error-exitcode=42 fails with:

 ==25252== Memcheck, a memory error detector
  ==25252== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al.
  ==25252== Using Valgrind-3.25.0.GIT-lbmacos and LibVEX; rerun with -h for copyright info
  ==25252== Command: ./recovery_example
  ==25252== 
  --25252-- run: /usr/bin/dsymutil "./recovery_example"
  ==25252== Conditional jump or move depends on uninitialised value(s)
  ==25252==    at 0x7FF8025BF587: ??? (in /dev/macos/internals/[shared pmap])
  ==25252==    by 0x100003F66: main (recovery.c:9)
  ==25252== 
  ==25252== Use of uninitialised value of size 8
  ==25252==    at 0x7FF8025BF5A3: ??? (in /dev/macos/internals/[shared pmap])
  ==25252==    by 0x100003F66: main (recovery.c:9)
  ==25252== 
  ==25252== Use of uninitialised value of size 8
  ==25252==    at 0x7FF8025BF5A8: ??? (in /dev/macos/internals/[shared pmap])
  ==25252==    by 0x100003F66: main (recovery.c:9)
  ==25252== 
  ==25252== 
  ==25252== HEAP SUMMARY:
  ==25252==     in use at exit: 8,849 bytes in 176 blocks
  ==25252==   total heap usage: 186 allocs, 10 frees, 9,760 bytes allocated
  ==25252== 
  ==25252== LEAK SUMMARY:
  ==25252==    definitely lost: 4,288 bytes in 134 blocks
  ==25252==    indirectly lost: 0 bytes in 0 blocks
  ==25252==      possibly lost: 576 bytes in 2 blocks
  ==25252==    still reachable: 3,985 bytes in 40 blocks
  ==25252==         suppressed: 0 bytes in 0 blocks
  ==25252== Rerun with --leak-check=full to see details of leaked memory
  ==25252== 
  ==25252== Use --track-origins=yes to see where uninitialised values come from
  ==25252== For lists of detected and suppressed errors, rerun with: -s
  ==25252== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 127 from 38)
  FAIL recovery_example (exit status: 42)

This is on macOS 13.7.6 22H625.

See https://github.com/real-or-random/secp256k1/actions/runs/17097713282/job/48485986672 for the full failure in CI.

@josibake couldn't reproduce this on real x86_64 machine with Sequoia 15, and we've never seen it on ARM64 (also 15).

So this seems to be restricted to

  • macOS < 15, maybe < 14
  • maybe x86_64

Is this enough to produce a suppression rule? Or, if it's too vague, do you have machines to isolate this further?

Unfortunately, it seems that the symbol is not loaded at all. This is usually an issue with the symbol itself being missing from DYLD cache, or it could be a Valgrind bug. Otherwise, memcmp would be replaced by the Valgrind version.

Or would it make sense to fix this plausible root cause instead? (I have no idea what this entails.)

real-or-random avatar Aug 20 '25 12:08 real-or-random

Here's a rather minimal test case (recovery.c):

Thanks a lot for all these details!

Is this enough to produce a suppression rule? Or, if it's too vague, do you have machines to isolate this further?

We can but I am a bit worried it might hide actual issues. Here is a potential suppression:

{
   DYLDCacheCond
   Memcheck:Cond
   obj:/dev/macos/internals/[shared pmap]
   ...
}

{
   DYLDCacheValue8
   Memcheck:Value8
   obj:/dev/macos/internals/[shared pmap]
   ...
}

Feel free to test it with --suppressions=a_file_with_this_content.

Or would it make sense to fix this plausible root cause instead? (I have no idea what this entails.)

I would love to but I don't really have a suitable test machine for that. Could you check that program using --trace-redir=yes? It might be quite verbose while it loads all the dylib but at the end you should see something looking like this:

--72391-- REDIR: 0x18db36a40 (libsystem_platform.dylib:_platform_strlen) redirected to 0x105018be4 (_platform_strlen)
--72391-- REDIR: 0x18db392c0 (libsystem_platform.dylib:_platform_memmove) redirected to 0x10501b104 (_platform_memmove)
--72391-- REDIR: 0x18db3c4b0 (libsystem_platform.dylib:_platform_strncmp$VARIANT$Base) redirected to 0x105019908 (_platform_strncmp$VARIANT$Base)
--72391-- REDIR: 0x18db3c3b0 (libsystem_platform.dylib:_platform_strcmp$VARIANT$Base) redirected to 0x105019c54 (_platform_strcmp$VARIANT$Base)
--72391-- REDIR: 0x18db374f4 (libsystem_platform.dylib:_platform_strstr) redirected to 0x10501baf0 (_platform_strstr)
--72391-- REDIR: 0x18d900b74 (libsystem_malloc.dylib:malloc_default_zone) redirected to 0x105017db4 (malloc_default_zone)
--72391-- REDIR: 0x18db38ff0 (libsystem_platform.dylib:_platform_memset) redirected to 0x10501af44 (_platform_memset)
--72391-- REDIR: 0x18d909114 (libsystem_malloc.dylib:malloc_set_zone_name) redirected to 0x105017e98 (malloc_set_zone_name)
--72391-- REDIR: 0x18db369a0 (libsystem_platform.dylib:_platform_strnlen) redirected to 0x105018b84 (_platform_strnlen)
--72391-- REDIR: 0x18d91b328 (libsystem_malloc.dylib:malloc_type_malloc) redirected to 0x105010a24 (malloc_type_malloc)
--72391-- REDIR: 0x18d91b424 (libsystem_malloc.dylib:malloc_type_realloc) redirected to 0x105016814 (malloc_type_realloc)
--72391-- REDIR: 0x18d8ff674 (libsystem_malloc.dylib:free) redirected to 0x105012a1c (free)
--72391-- REDIR: 0x18d91b3ac (libsystem_malloc.dylib:malloc_type_calloc) redirected to 0x105015dec (malloc_type_calloc)
--72391-- REDIR: 0x18d905408 (libsystem_malloc.dylib:malloc_size) redirected to 0x105017b90 (malloc_size)
--72391-- REDIR: 0x18db36d10 (libsystem_platform.dylib:_platform_strcpy) redirected to 0x105018d94 (_platform_strcpy)
--72391-- REDIR: 0x18d991660 (libsystem_c.dylib:strrchr) redirected to 0x10501832c (strrchr)
--72391-- REDIR: 0x18d937fc4 (libsystem_malloc.dylib:malloc_type_posix_memalign) redirected to 0x105017804 (malloc_type_posix_memalign)
--72391-- REDIR: 0x18d93808c (libsystem_malloc.dylib:malloc_type_zone_malloc_with_options_internal) redirected to 0x10501820c (malloc_type_zone_malloc_with_options_internal)
--72391-- REDIR: 0x18db36e90 (libsystem_platform.dylib:_platform_memcmp) redirected to 0x10501a564 (_platform_memcmp)
==72391==
==72391== HEAP SUMMARY:
==72391==     in use at exit: 9,483 bytes in 183 blocks
==72391==   total heap usage: 197 allocs, 14 frees, 10,296 bytes allocated
==72391==
==72391== LEAK SUMMARY:
==72391==    definitely lost: 4,320 bytes in 135 blocks
==72391==    indirectly lost: 0 bytes in 0 blocks
==72391==      possibly lost: 648 bytes in 4 blocks
==72391==    still reachable: 4,515 bytes in 44 blocks
==72391==         suppressed: 0 bytes in 0 blocks
==72391== Rerun with --leak-check=full to see details of leaked memory

Note that only the last line, _platform_memcmp actual correspond to anything happening in main. But it shows that the function gets rewritten by Valgrind (so it can keep track of memory better). Give it a go, if there is no such line, then shared/vg_replace_strmem.c needs to be updated. I have done a round of updates recently but mostly for arm64.

LouisBrunner avatar Aug 20 '25 17:08 LouisBrunner

No memcmp here:

2025-08-20T19:08:15.6292800Z --23240-- REDIR: 0x7ff812182146 (libsystem_malloc.dylib:malloc_default_zone) redirected to 0x1001801c5 (malloc_default_zone)
2025-08-20T19:08:15.6293810Z --23240-- REDIR: 0x7ff81218a99a (libsystem_malloc.dylib:malloc_set_zone_name) redirected to 0x100180296 (malloc_set_zone_name)
2025-08-20T19:08:15.6294380Z --23240-- REDIR: 0x7ff81217ff20 (libsystem_malloc.dylib:malloc) redirected to 0x10017a9c4 (malloc)
2025-08-20T19:08:15.6295020Z --23240-- REDIR: 0x7ff812181cb1 (libsystem_malloc.dylib:realloc) redirected to 0x10017f1a8 (realloc)
2025-08-20T19:08:15.6295770Z --23240-- REDIR: 0x7ff81217ff34 (libsystem_malloc.dylib:malloc_zone_malloc) redirected to 0x10017ac66 (malloc_zone_malloc)
2025-08-20T19:08:15.6296440Z --23240-- REDIR: 0x7ff812181e37 (libsystem_malloc.dylib:malloc_zone_calloc) redirected to 0x10017f016 (malloc_zone_calloc)
2025-08-20T19:08:15.6297130Z --23240-- REDIR: 0x7ff81218214e (libsystem_malloc.dylib:malloc_zone_from_ptr) redirected to 0x100180206 (malloc_zone_from_ptr)
2025-08-20T19:08:15.6297660Z --23240-- REDIR: 0x7ff8121809e6 (libsystem_malloc.dylib:free) redirected to 0x10017c846 (free)
2025-08-20T19:08:15.6298230Z --23240-- REDIR: 0x7ff812181e20 (libsystem_malloc.dylib:calloc) redirected to 0x10017edf6 (calloc)
2025-08-20T19:08:15.6298910Z --23240-- REDIR: 0x7ff8121868f6 (libsystem_malloc.dylib:malloc_size) redirected to 0x10018000d (malloc_size)
2025-08-20T19:08:15.6299510Z --23240-- REDIR: 0x7ff8121f8ae3 (libsystem_c.dylib:strrchr) redirected to 0x100180367 (strrchr)

But there are many REDIR STATES that mention memcmp. The last REDIR STATE, immediately above the REDIR lines:

2025-08-20T19:08:15.6183520Z --23240--    ------ REDIR STATE after VG_(redir_notify_new_DebugInfo) ------
2025-08-20T19:08:15.6183950Z --23240--    TOPSPECS of soname libcache.dylib filename /usr/lib/system/libcache.dylib
2025-08-20T19:08:15.6184620Z --23240--    TOPSPECS of soname libsystem_dnssd.dylib filename /usr/lib/system/libsystem_dnssd.dylib
2025-08-20T19:08:15.6185040Z --23240--    TOPSPECS of soname libkeymgr.dylib filename /usr/lib/system/libkeymgr.dylib
2025-08-20T19:08:15.6185530Z --23240--    TOPSPECS of soname libremovefile.dylib filename /usr/lib/system/libremovefile.dylib
2025-08-20T19:08:15.6186070Z --23240--    TOPSPECS of soname libsystem_secinit.dylib filename /usr/lib/system/libsystem_secinit.dylib
2025-08-20T19:08:15.6186660Z --23240--    TOPSPECS of soname libsystem_collections.dylib filename /usr/lib/system/libsystem_collections.dylib
2025-08-20T19:08:15.6187160Z --23240--    TOPSPECS of soname libcompiler_rt.dylib filename /usr/lib/system/libcompiler_rt.dylib
2025-08-20T19:08:15.6187620Z --23240--    TOPSPECS of soname libcopyfile.dylib filename /usr/lib/system/libcopyfile.dylib
2025-08-20T19:08:15.6187950Z --23240--    TOPSPECS of soname liboah.dylib filename /usr/lib/liboah.dylib
2025-08-20T19:08:15.6188380Z --23240--    TOPSPECS of soname libunwind.dylib filename /usr/lib/system/libunwind.dylib
2025-08-20T19:08:15.6189420Z --23240--    TOPSPECS of soname libcommonCrypto.dylib filename /usr/lib/system/libcommonCrypto.dylib
2025-08-20T19:08:15.6189830Z --23240--    TOPSPECS of soname libmacho.dylib filename /usr/lib/system/libmacho.dylib
2025-08-20T19:08:15.6190270Z --23240--    TOPSPECS of soname libsystem_m.dylib filename /usr/lib/system/libsystem_m.dylib
2025-08-20T19:08:15.6190890Z --23240--    TOPSPECS of soname libsystem_coreservices.dylib filename /usr/lib/system/libsystem_coreservices.dylib
2025-08-20T19:08:15.6191370Z --23240--    TOPSPECS of soname libquarantine.dylib filename /usr/lib/system/libquarantine.dylib
2025-08-20T19:08:15.6192040Z --23240--    TOPSPECS of soname libsystem_sandbox.dylib filename /usr/lib/system/libsystem_sandbox.dylib
2025-08-20T19:08:15.6192670Z --23240--    TOPSPECS of soname libsystem_configuration.dylib filename /usr/lib/system/libsystem_configuration.dylib
2025-08-20T19:08:15.6193440Z --23240--    TOPSPECS of soname libsystem_containermanager.dylib filename /usr/lib/system/libsystem_containermanager.dylib
2025-08-20T19:08:15.6194070Z --23240--    TOPSPECS of soname libsystem_symptoms.dylib filename /usr/lib/system/libsystem_symptoms.dylib
2025-08-20T19:08:15.6194630Z --23240--    TOPSPECS of soname libsystem_asl.dylib filename /usr/lib/system/libsystem_asl.dylib
2025-08-20T19:08:15.6195440Z --23240--    TOPSPECS of soname libsystem_networkextension.dylib filename /usr/lib/system/libsystem_networkextension.dylib
2025-08-20T19:08:15.6196080Z --23240--    TOPSPECS of soname libsystem_notify.dylib filename /usr/lib/system/libsystem_notify.dylib
2025-08-20T19:08:15.6196730Z --23240--    TOPSPECS of soname libsystem_darwin.dylib filename /usr/lib/system/libsystem_darwin.dylib
2025-08-20T19:08:15.6197560Z --23240--    TOPSPECS of soname libsystem_info.dylib filename /usr/lib/system/libsystem_info.dylib
2025-08-20T19:08:15.6198020Z --23240--    TOPSPECS of soname libdyld.dylib filename /usr/lib/system/libdyld.dylib
2025-08-20T19:08:15.6198720Z --23240--    TOPSPECS of soname libc++abi.dylib filename /usr/lib/libc++abi.dylib
2025-08-20T19:08:15.6199140Z --23240--    TOPSPECS of soname libc++.1.dylib filename /usr/lib/libc++.1.dylib
2025-08-20T19:08:15.6199710Z --23240--    TOPSPECS of soname libsystem_c.dylib filename /usr/lib/system/libsystem_c.dylib
2025-08-20T19:08:15.6200460Z --23240--    TOPSPECS of soname libsystem_featureflags.dylib filename /usr/lib/system/libsystem_featureflags.dylib
2025-08-20T19:08:15.6200930Z --23240--    TOPSPECS of soname libdispatch.dylib filename /usr/lib/system/libdispatch.dylib
2025-08-20T19:08:15.6201450Z --23240--    TOPSPECS of soname libsystem_malloc.dylib filename /usr/lib/system/libsystem_malloc.dylib
2025-08-20T19:08:15.6201940Z --23240--    TOPSPECS of soname libcorecrypto.dylib filename /usr/lib/system/libcorecrypto.dylib
2025-08-20T19:08:15.6202440Z --23240--    TOPSPECS of soname libsystem_trace.dylib filename /usr/lib/system/libsystem_trace.dylib
2025-08-20T19:08:15.6202810Z --23240--    TOPSPECS of soname libxpc.dylib filename /usr/lib/system/libxpc.dylib
2025-08-20T19:08:15.6203330Z --23240--    TOPSPECS of soname libsystem_blocks.dylib filename /usr/lib/system/libsystem_blocks.dylib
2025-08-20T19:08:15.6203700Z --23240--    TOPSPECS of soname libobjc.A.dylib filename /usr/lib/libobjc.A.dylib
2025-08-20T19:08:15.6204100Z --23240--    TOPSPECS of soname libSystem.B.dylib filename /usr/lib/libSystem.B.dylib
2025-08-20T19:08:15.6205140Z --23240--    TOPSPECS of soname vgpreload_memcheck-amd64-darwin.so filename /usr/local/Cellar/valgrind/HEAD-84379f5/libexec/valgrind/vgpreload_memcheck-amd64-darwin.so
2025-08-20T19:08:15.6205530Z --23240--      libsystem_malloc.dylib    memccpy                        RL-> (2049.0) 0x1001818a0
2025-08-20T19:08:15.6205990Z --23240--      libsystem_platform.dylib  _platform_memmove$VARIANT$Ivyb RL-> (2018.1) 0x100181680
2025-08-20T19:08:15.6206420Z --23240--      libsystem_malloc.dylib    memmove$VARIANT$sse42          RL-> (2018.1) 0x100181460
2025-08-20T19:08:15.6206840Z --23240--      libsystem_malloc.dylib    memmove$VARIANT$sse3x          RL-> (2018.1) 0x100181240
2025-08-20T19:08:15.6207340Z --23240--      libsystem_malloc.dylib    memset                         RL-> (2021.0) 0x1001811ac
2025-08-20T19:08:15.6207770Z --23240--      libsystem_platform.dylib  _platform_memcmp               RL-> (2019.0) 0x100181161
2025-08-20T19:08:15.6208190Z --23240--      libsystem_malloc.dylib    memcpy$VARIANT$sse42           RL-> (2018.0) 0x100180eeb
2025-08-20T19:08:15.6208620Z --23240--      libsystem_malloc.dylib    memcpy$VARIANT$sse3x           RL-> (2018.0) 0x100180c75
2025-08-20T19:08:15.6209130Z --23240--      libsystem_platform.dylib  _platform_memchr$VARIANT$Base  RL-> (2017.0) 0x100180c58
2025-08-20T19:08:15.6209590Z --23240--      libsystem_platform.dylib  _platform_memchr$VARIANT$Haswe RL-> (2017.0) 0x100180c3b
2025-08-20T19:08:15.6210040Z --23240--      libsystem_platform.dylib  _platform_memchr$VARIANT$Gener RL-> (2017.0) 0x100180c1e
2025-08-20T19:08:15.6210290Z --23240--      dyld                      memchr                         RL-> (2017.0) 0x100180c01
2025-08-20T19:08:15.6210730Z --23240--      libsystem_platform.dylib  _platform_strcmp               RL-> (2016.0) 0x100180bca
2025-08-20T19:08:15.6211120Z --23240--      libsystem_malloc.dylib    strcmp                         RL-> (2016.0) 0x100180b93
2025-08-20T19:08:15.6211550Z --23240--      libsystem_platform.dylib  _platform_strncmp              RL-> (2011.0) 0x100180b4e
2025-08-20T19:08:15.6211940Z --23240--      libsystem_malloc.dylib    strncmp                        RL-> (2011.0) 0x100180b09
2025-08-20T19:08:15.6212320Z --23240--      libsystem_malloc.dylib    strlcpy                        RL-> (2010.0) 0x100180a0e
2025-08-20T19:08:15.6212840Z --23240--      libsystem_c.dylib         __strncpy_chk                  RL-> (2009.0) 0x100180921
2025-08-20T19:08:15.6213190Z --23240--      libsystem_c.dylib         strncpy                        RL-> (2009.0) 0x100180834
2025-08-20T19:08:15.6213700Z --23240--      libsystem_malloc.dylib    strncpy                        RL-> (2009.0) 0x100180747
2025-08-20T19:08:15.6214060Z --23240--      libsystem_c.dylib         __strcpy_chk                   RL-> (2008.0) 0x1001806aa
2025-08-20T19:08:15.6214440Z --23240--      libsystem_malloc.dylib    strcpy                         RL-> (2008.0) 0x10018060d
2025-08-20T19:08:15.6214780Z --23240--      libsystem_c.dylib         strlen                         RL-> (2007.0) 0x1001805f5
2025-08-20T19:08:15.6215150Z --23240--      libsystem_malloc.dylib    strlen                         RL-> (2007.0) 0x1001805dd
2025-08-20T19:08:15.6215540Z --23240--      libsystem_malloc.dylib    strlcat                        RL-> (2005.0) 0x1001804bd
2025-08-20T19:08:15.6215900Z --23240--      libsystem_c.dylib         __strncat_chk                  RL-> (2004.0) 0x10018040f
2025-08-20T19:08:15.6216350Z --23240--      libsystem_platform.dylib  _platform_strchr$VARIANT$Base  RL-> (2002.0) 0x1001803ec
2025-08-20T19:08:15.6216810Z --23240--      libsystem_platform.dylib  _platform_strchr$VARIANT$Haswe RL-> (2002.0) 0x1001803c9
2025-08-20T19:08:15.6217260Z --23240--      libsystem_platform.dylib  _platform_strchr$VARIANT$Gener RL-> (2002.0) 0x1001803a6
2025-08-20T19:08:15.6217630Z --23240--      libsystem_malloc.dylib    strchr                         RL-> (2002.0) 0x100180383
2025-08-20T19:08:15.6217970Z --23240--      libsystem_c.dylib         strrchr                        RL-> (2001.0) 0x100180367
2025-08-20T19:08:15.6218360Z --23240--      libsystem_malloc.dylib    strrchr                        RL-> (2001.0) 0x10018034b
2025-08-20T19:08:15.6218630Z --23240--      *                         malloc_get_zone_name           RG-> (1029.0) 0x1001802c0
2025-08-20T19:08:15.6219050Z --23240--      libsystem_malloc.dylib    malloc_get_zone_name           RL-> (1029.0) 0x1001802ae
2025-08-20T19:08:15.6219320Z --23240--      *                         malloc_set_zone_name           RG-> (1028.0) 0x1001802a2
2025-08-20T19:08:15.6219740Z --23240--      libsystem_malloc.dylib    malloc_set_zone_name           RL-> (1028.0) 0x100180296
2025-08-20T19:08:15.6220070Z --23240--      *                         malloc_zone_unregister         RG-> (1027.0) 0x10018028a
2025-08-20T19:08:15.6220490Z --23240--      libsystem_malloc.dylib    malloc_zone_unregister         RL-> (1027.0) 0x10018027e
2025-08-20T19:08:15.6220760Z --23240--      *                         malloc_zone_register           RG-> (1026.0) 0x100180272
2025-08-20T19:08:15.6221180Z --23240--      libsystem_malloc.dylib    malloc_zone_register           RL-> (1026.0) 0x100180266
2025-08-20T19:08:15.6221500Z --23240--      *                         malloc_zone_check              RG-> (1025.0) 0x100180243
2025-08-20T19:08:15.6221920Z --23240--      libsystem_malloc.dylib    malloc_zone_check              RL-> (1025.0) 0x100180220
2025-08-20T19:08:15.6222180Z --23240--      *                         malloc_zone_from_ptr           RG-> (1024.0) 0x100180213
2025-08-20T19:08:15.6222610Z --23240--      libsystem_malloc.dylib    malloc_zone_from_ptr           RL-> (1024.0) 0x100180206
2025-08-20T19:08:15.6223030Z --23240--      libsystem_malloc.dylib    malloc_create_zone             RL-> (1023.0) 0x1001801f9
2025-08-20T19:08:15.6223310Z --23240--      *                         malloc_default_purgeable_zone  RG-> (1022.0) 0x1001801ec
2025-08-20T19:08:15.6223750Z --23240--      libsystem_malloc.dylib    malloc_default_purgeable_zone  RL-> (1022.0) 0x1001801df
2025-08-20T19:08:15.6224020Z --23240--      *                         malloc_default_zone            RG-> (1022.0) 0x1001801d2
2025-08-20T19:08:15.6224440Z --23240--      libsystem_malloc.dylib    malloc_default_zone            RL-> (1022.0) 0x1001801c5
2025-08-20T19:08:15.6224990Z --23240--      libsystem_malloc.dylib    malloc_set_state               RL-> (1019.0) 0x1001801a7
2025-08-20T19:08:15.6225400Z --23240--      libsystem_malloc.dylib    malloc_get_state               RL-> (1019.0) 0x100180189
2025-08-20T19:08:15.6225910Z --23240--      libsystem_malloc.dylib    pvalloc                        RL-> (1019.0) 0x10018016b
2025-08-20T19:08:15.6226170Z --23240--      *                         malloc_size                    RG-> (1018.0) 0x1001800bc
2025-08-20T19:08:15.6226560Z --23240--      libsystem_malloc.dylib    malloc_size                    RL-> (1018.0) 0x10018000d
2025-08-20T19:08:15.6226960Z --23240--      libsystem_malloc.dylib    aligned_alloc                  RL-> (1017.0) 0x10017fe6e
2025-08-20T19:08:15.6227380Z --23240--      libsystem_malloc.dylib    posix_memalign                 RL-> (1016.0) 0x10017fd06
2025-08-20T19:08:15.6227650Z --23240--      *                         malloc_zone_valloc             RG-> (1013.0) 0x10017fc80
2025-08-20T19:08:15.6228070Z --23240--      libsystem_malloc.dylib    malloc_zone_valloc             RL-> (1013.0) 0x10017fbfa
2025-08-20T19:08:15.6228290Z --23240--      *                         valloc                         RG-> (1012.0) 0x10017fb32
2025-08-20T19:08:15.6228670Z --23240--      libsystem_malloc.dylib    valloc                         RL-> (1012.0) 0x10017fa6a
2025-08-20T19:08:15.6228940Z --23240--      *                         malloc_zone_memalign           RG-> (1010.0) 0x10017f8eb
2025-08-20T19:08:15.6229360Z --23240--      libsystem_malloc.dylib    malloc_zone_memalign           RL-> (1010.0) 0x10017f76c
2025-08-20T19:08:15.6229630Z --23240--      *                         malloc_zone_realloc            RG-> (1008.0) 0x10017f67a
2025-08-20T19:08:15.6230050Z --23240--      libsystem_malloc.dylib    malloc_zone_realloc            RL-> (1008.0) 0x10017f588
2025-08-20T19:08:15.6230280Z --23240--      *                         reallocf                       RG-> (1009.1) 0x10017f480
2025-08-20T19:08:15.6230690Z --23240--      libsystem_malloc.dylib    reallocf                       RL-> (1009.1) 0x10017f378
2025-08-20T19:08:15.6230920Z --23240--      *                         realloc                        RG-> (1009.0) 0x10017f290
2025-08-20T19:08:15.6231310Z --23240--      libsystem_malloc.dylib    realloc                        RL-> (1009.0) 0x10017f1a8
2025-08-20T19:08:15.6231770Z --23240--      *                         malloc_zone_calloc             RG-> (1006.0) 0x10017f0df
2025-08-20T19:08:15.6232210Z --23240--      libsystem_malloc.dylib    malloc_zone_calloc             RL-> (1006.0) 0x10017f016
2025-08-20T19:08:15.6232430Z --23240--      *                         calloc                         RG-> (1007.0) 0x10017ef06
2025-08-20T19:08:15.6232820Z --23240--      libsystem_malloc.dylib    calloc                         RL-> (1007.0) 0x10017edf6
2025-08-20T19:08:15.6233110Z --23240--      *                         _ZdaPvSt11align_val_tRKSt9noth RG-> (1005.0) 0x10017ed03
2025-08-20T19:08:15.6233670Z --23240--      libc++*                   _ZdaPvSt11align_val_tRKSt9noth RL-> (1005.0) 0x10017ec10
2025-08-20T19:08:15.6234110Z --23240--      libstdc++*                _ZdaPvSt11align_val_tRKSt9noth RL-> (1005.0) 0x10017eb1d
2025-08-20T19:08:15.6234610Z --23240--      libsystem_malloc.dylib    _ZdaPvRKSt9nothrow_t           RL-> (1005.0) 0x10017ea3b
2025-08-20T19:08:15.6235050Z --23240--      libc++*                   _ZdaPvRKSt9nothrow_t           RL-> (1005.0) 0x10017e959
2025-08-20T19:08:15.6235460Z --23240--      libstdc++*                _ZdaPvRKSt9nothrow_t           RL-> (1005.0) 0x10017e877
2025-08-20T19:08:15.6235820Z --23240--      *                         _ZdaPvmSt11align_val_t         RG-> (1005.0) 0x10017e77c
2025-08-20T19:08:15.6236200Z --23240--      libc++*                   _ZdaPvmSt11align_val_t         RL-> (1005.0) 0x10017e681
2025-08-20T19:08:15.6236610Z --23240--      libstdc++*                _ZdaPvmSt11align_val_t         RL-> (1005.0) 0x10017e586
2025-08-20T19:08:15.6237020Z --23240--      *                         _ZdaPvSt11align_val_t          RG-> (1005.0) 0x10017e493
2025-08-20T19:08:15.6237650Z --23240--      libc++*                   _ZdaPvSt11align_val_t          RL-> (1005.0) 0x10017e3a0
2025-08-20T19:08:15.6238300Z --23240--      libstdc++*                _ZdaPvSt11align_val_t          RL-> (1005.0) 0x10017e2ad
2025-08-20T19:08:15.6238550Z --23240--      *                         _ZdaPvm                        RG-> (1005.0) 0x10017e1ba
2025-08-20T19:08:15.6238930Z --23240--      libc++*                   _ZdaPvm                        RL-> (1005.0) 0x10017e0c7
2025-08-20T19:08:15.6239230Z --23240--      libstdc++*                _ZdaPvm                        RL-> (1005.0) 0x10017dfd4
2025-08-20T19:08:15.6239570Z --23240--      *                         _ZdaPv                         RG-> (1005.0) 0x10017def2
2025-08-20T19:08:15.6239840Z --23240--      libc++*                   _ZdaPv                         RL-> (1005.0) 0x10017de10
2025-08-20T19:08:15.6240180Z --23240--      libstdc++*                _ZdaPv                         RL-> (1005.0) 0x10017dd2e
2025-08-20T19:08:15.6240550Z --23240--      *                         _ZdlPvSt11align_val_tRKSt9noth RG-> (1005.0) 0x10017dc3b
2025-08-20T19:08:15.6240990Z --23240--      libc++*                   _ZdlPvSt11align_val_tRKSt9noth RL-> (1005.0) 0x10017db48
2025-08-20T19:08:15.6241410Z --23240--      libstdc++*                _ZdlPvSt11align_val_tRKSt9noth RL-> (1005.0) 0x10017da55
2025-08-20T19:08:15.6241780Z --23240--      *                         _ZdlPvRKSt9nothrow_t           RG-> (1005.0) 0x10017d973
2025-08-20T19:08:15.6242160Z --23240--      libc++*                   _ZdlPvRKSt9nothrow_t           RL-> (1005.0) 0x10017d891
2025-08-20T19:08:15.6242570Z --23240--      libstdc++*                _ZdlPvRKSt9nothrow_t           RL-> (1005.0) 0x10017d7af
2025-08-20T19:08:15.6242980Z --23240--      *                         _ZdlPvmSt11align_val_t         RG-> (1005.0) 0x10017d6b4
2025-08-20T19:08:15.6243350Z --23240--      libc++*                   _ZdlPvmSt11align_val_t         RL-> (1005.0) 0x10017d5b9
2025-08-20T19:08:15.6243770Z --23240--      libstdc++*                _ZdlPvmSt11align_val_t         RL-> (1005.0) 0x10017d4be
2025-08-20T19:08:15.6244580Z --23240--      *                         _ZdlPvSt11align_val_t          RG-> (1005.0) 0x10017d3cb
2025-08-20T19:08:15.6245090Z --23240--      libc++*                   _ZdlPvSt11align_val_t          RL-> (1005.0) 0x10017d2d8
2025-08-20T19:08:15.6245670Z --23240--      libstdc++*                _ZdlPvSt11align_val_t          RL-> (1005.0) 0x10017d1e5
2025-08-20T19:08:15.6245980Z --23240--      *                         _ZdlPvm                        RG-> (1005.0) 0x10017d0f2
2025-08-20T19:08:15.6246310Z --23240--      libc++*                   _ZdlPvm                        RL-> (1005.0) 0x10017cfff
2025-08-20T19:08:15.6246660Z --23240--      libstdc++*                _ZdlPvm                        RL-> (1005.0) 0x10017cf0c
2025-08-20T19:08:15.6247090Z --23240--      *                         _ZdlPv                         RG-> (1005.0) 0x10017ce2a
2025-08-20T19:08:15.6247420Z --23240--      libc++*                   _ZdlPv                         RL-> (1005.0) 0x10017cd48
2025-08-20T19:08:15.6247770Z --23240--      libstdc++*                _ZdlPv                         RL-> (1005.0) 0x10017cc66
2025-08-20T19:08:15.6248120Z --23240--      *                         free_sized                     RG-> (1005.1) 0x10017cb73
2025-08-20T19:08:15.6248590Z --23240--      libsystem_malloc.dylib    free_sized                     RL-> (1005.1) 0x10017ca80
2025-08-20T19:08:15.6248930Z --23240--      *                         malloc_zone_free               RG-> (1004.0) 0x10017c9ea
2025-08-20T19:08:15.6249470Z --23240--      libsystem_malloc.dylib    malloc_zone_free               RL-> (1004.0) 0x10017c954
2025-08-20T19:08:15.6249700Z --23240--      *                         free                           RG-> (1005.0) 0x10017c8cd
2025-08-20T19:08:15.6250180Z --23240--      libsystem_malloc.dylib    free                           RL-> (1005.0) 0x10017c846
2025-08-20T19:08:15.6250810Z --23240--      *                         _ZnamSt11align_val_tRKSt9nothr RG-> (1001.0) 0x10017c702
2025-08-20T19:08:15.6251210Z --23240--      libc++*                   _ZnamSt11align_val_tRKSt9nothr RL-> (1001.0) 0x10017c5be
2025-08-20T19:08:15.6251870Z --23240--      libstdc++*                _ZnamSt11align_val_tRKSt9nothr RL-> (1001.0) 0x10017c47a
2025-08-20T19:08:15.6252230Z --23240--      *                         _ZnamRKSt9nothrow_t            RG-> (1001.0) 0x10017c3b5
2025-08-20T19:08:15.6252620Z --23240--      libc++*                   _ZnamRKSt9nothrow_t            RL-> (1001.0) 0x10017c2f0
2025-08-20T19:08:15.6253030Z --23240--      libstdc++*                _ZnamRKSt9nothrow_t            RL-> (1001.0) 0x10017c22b
2025-08-20T19:08:15.6253370Z --23240--      *                         _ZnamSt11align_val_t           RG-> (1003.0) 0x10017c0df
2025-08-20T19:08:15.6253750Z --23240--      libc++*                   _ZnamSt11align_val_t           RL-> (1003.0) 0x10017bf93
2025-08-20T19:08:15.6254210Z --23240--      libstdc++*                _ZnamSt11align_val_t           RL-> (1003.0) 0x10017be47
2025-08-20T19:08:15.6254430Z --23240--      *                         _Znam                          RG-> (1003.0) 0x10017bd76
2025-08-20T19:08:15.6254740Z --23240--      libc++*                   _Znam                          RL-> (1003.0) 0x10017bca5
2025-08-20T19:08:15.6255090Z --23240--      libstdc++*                _Znam                          RL-> (1003.0) 0x10017bbd4
2025-08-20T19:08:15.6255490Z --23240--      *                         _ZnwmSt11align_val_tRKSt9nothr RG-> (1001.0) 0x10017ba90
2025-08-20T19:08:15.6255830Z --23240--      libc++*                   _ZnwmSt11align_val_tRKSt9nothr RL-> (1001.0) 0x10017b94c
2025-08-20T19:08:15.6256170Z --23240--      libstdc++*                _ZnwmSt11align_val_tRKSt9nothr RL-> (1001.0) 0x10017b808
2025-08-20T19:08:15.6256450Z --23240--      *                         _ZnwmRKSt9nothrow_t            RG-> (1001.0) 0x10017b743
2025-08-20T19:08:15.6256760Z --23240--      libc++*                   _ZnwmRKSt9nothrow_t            RL-> (1001.0) 0x10017b67e
2025-08-20T19:08:15.6257090Z --23240--      libstdc++*                _ZnwmRKSt9nothrow_t            RL-> (1001.0) 0x10017b5b9
2025-08-20T19:08:15.6257370Z --23240--      *                         _ZnwmSt11align_val_t           RG-> (1003.0) 0x10017b46d
2025-08-20T19:08:15.6257780Z --23240--      libc++*                   _ZnwmSt11align_val_t           RL-> (1003.0) 0x10017b321
2025-08-20T19:08:15.6258120Z --23240--      libstdc++*                _ZnwmSt11align_val_t           RL-> (1003.0) 0x10017b1d5
2025-08-20T19:08:15.6258320Z --23240--      *                         _Znwm                          RG-> (1003.0) 0x10017b104
2025-08-20T19:08:15.6258560Z --23240--      libc++*                   _Znwm                          RL-> (1003.0) 0x10017b033
2025-08-20T19:08:15.6258900Z --23240--      libstdc++*                _Znwm                          RL-> (1003.0) 0x10017adda
2025-08-20T19:08:15.6259170Z --23240--      *                         malloc_zone_malloc             RG-> (1002.0) 0x10017ad20
2025-08-20T19:08:15.6259580Z --23240--      libsystem_malloc.dylib    malloc_zone_malloc             RL-> (1002.0) 0x10017ac66
2025-08-20T19:08:15.6259820Z --23240--      *                         malloc                         RG-> (1001.0) 0x10017aba1
2025-08-20T19:08:15.6260190Z --23240--      libsystem_malloc.dylib    malloc                         RL-> (1001.0) 0x10017a9c4
2025-08-20T19:08:15.6261160Z --23240--    TOPSPECS of soname vgpreload_core-amd64-darwin.so filename /usr/local/Cellar/valgrind/HEAD-84379f5/libexec/valgrind/vgpreload_core-amd64-darwin.so
2025-08-20T19:08:15.6261550Z --23240--      libSystem.*.dylib         arc4random_addrandom           RL-> (0000.0) 0x100159ebf
2025-08-20T19:08:15.6261920Z --23240--      libSystem.*.dylib         arc4random_stir                RL-> (0000.0) 0x100159eb9
2025-08-20T19:08:15.6262280Z --23240--      libSystem.*.dylib         arc4random                     RL-> (0000.0) 0x100159e77
2025-08-20T19:08:15.6262670Z --23240--    TOPSPECS of soname dyld filename /usr/lib/dyld
2025-08-20T19:08:15.6262930Z --23240--    TOPSPECS of soname NONE filename ./recovery_example
2025-08-20T19:08:15.6263210Z --23240--    TOPSPECS of soname (hardwired)
2025-08-20T19:08:15.6263490Z --23240--      dyld                      arc4random                     RL-> (0000.0) 0x158054bde
2025-08-20T19:08:15.6263750Z --23240--      dyld                      strlcat                        RL-> (0000.0) 0x158054b79
2025-08-20T19:08:15.6264000Z --23240--      dyld                      strcpy                         RL-> (0000.0) 0x158054b5c
2025-08-20T19:08:15.6264260Z --23240--      dyld                      strcat                         RL-> (0000.0) 0x158054b20
2025-08-20T19:08:15.6264500Z --23240--      dyld                      strlen                         RL-> (0000.0) 0x158054b0f
2025-08-20T19:08:15.6264750Z --23240--      dyld                      strcmp                         RL-> (0000.0) 0x158054b40
2025-08-20T19:08:15.6264880Z --23240--    ------ ACTIVE ------
2025-08-20T19:08:15.6265160Z --23240--     0x10000dd20 (strlen              ) R-> (0000.0) 0x158054b0f ???
2025-08-20T19:08:15.6265440Z --23240--     0x10000dd80 (strcpy              ) R-> (0000.0) 0x158054b5c ???
2025-08-20T19:08:15.6265720Z --23240--     0x10000ecc0 (strcmp              ) R-> (0000.0) 0x158054b40 ???
2025-08-20T19:08:15.6266000Z --23240--     0x10000f1b0 (strlcat             ) R-> (0000.0) 0x158054b79 ???
2025-08-20T19:08:15.6266270Z --23240--     0x100010a41 (strcat              ) R-> (0000.0) 0x158054b20 ???
2025-08-20T19:08:15.6266550Z --23240--     0x100011300 (memchr              ) R-> (2017.0) 0x100180c01 memchr
2025-08-20T19:08:15.6266840Z --23240--     0x10006f960 (arc4random          ) R-> (0000.0) 0x158054bde ???
2025-08-20T19:08:15.6267150Z --23240--     0x7ff81217ff20 (malloc              ) R-> (1001.0) 0x10017a9c4 malloc
2025-08-20T19:08:15.6267560Z --23240--     0x7ff81217ff34 (malloc_zone_malloc  ) R-> (1002.0) 0x10017ac66 malloc_zone_malloc
2025-08-20T19:08:15.6267860Z --23240--     0x7ff8121809e6 (free                ) R-> (1005.0) 0x10017c846 free
2025-08-20T19:08:15.6268180Z --23240--     0x7ff812181cb1 (realloc             ) R-> (1009.0) 0x10017f1a8 realloc
2025-08-20T19:08:15.6268490Z --23240--     0x7ff812181e20 (calloc              ) R-> (1007.0) 0x10017edf6 calloc
2025-08-20T19:08:15.6268960Z --23240--     0x7ff812181e37 (malloc_zone_calloc  ) R-> (1006.0) 0x10017f016 malloc_zone_calloc
2025-08-20T19:08:15.6269390Z --23240--     0x7ff812182146 (malloc_default_zone ) R-> (1022.0) 0x1001801c5 malloc_default_zone
2025-08-20T19:08:15.6269810Z --23240--     0x7ff81218214e (malloc_zone_from_ptr) R-> (1024.0) 0x100180206 malloc_zone_from_ptr
2025-08-20T19:08:15.6270220Z --23240--     0x7ff81218325b (malloc_zone_realloc ) R-> (1008.0) 0x10017f588 malloc_zone_realloc
2025-08-20T19:08:15.6270670Z --23240--     0x7ff8121867e1 (malloc_zone_free    ) R-> (1004.0) 0x10017c954 malloc_zone_free
2025-08-20T19:08:15.6271010Z --23240--     0x7ff8121868f6 (malloc_size         ) R-> (1018.0) 0x10018000d malloc_size
2025-08-20T19:08:15.6271430Z --23240--     0x7ff8121869c7 (malloc_zone_memalign) R-> (1010.0) 0x10017f76c malloc_zone_memalign
2025-08-20T19:08:15.6271750Z --23240--     0x7ff812188aa9 (valloc              ) R-> (1012.0) 0x10017fa6a valloc
2025-08-20T19:08:15.6272160Z --23240--     0x7ff812188abd (malloc_zone_valloc  ) R-> (1013.0) 0x10017fbfa malloc_zone_valloc
2025-08-20T19:08:15.6272540Z --23240--     0x7ff812188b57 (posix_memalign      ) R-> (1016.0) 0x10017fd06 posix_memalign
2025-08-20T19:08:15.6272980Z --23240--     0x7ff81218970c (malloc_zone_register) R-> (1026.0) 0x100180266 malloc_zone_register
2025-08-20T19:08:15.6273380Z --23240--     0x7ff81218a065 (malloc_create_zone  ) R-> (1023.0) 0x1001801f9 malloc_create_zone
2025-08-20T19:08:15.6273800Z --23240--     0x7ff81218a99a (malloc_set_zone_name) R-> (1028.0) 0x100180296 malloc_set_zone_name
2025-08-20T19:08:15.6274440Z --23240--     0x7ff81218b695 (malloc_default_purge) R-> (1022.0) 0x1001801df malloc_default_purgeable_zone
2025-08-20T19:08:15.6274890Z --23240--     0x7ff8121906a6 (malloc_zone_unregist) R-> (1027.0) 0x10018027e malloc_zone_unregister
2025-08-20T19:08:15.6275440Z --23240--     0x7ff81219d071 (malloc_get_zone_name) R-> (1029.0) 0x1001802ae malloc_get_zone_name
2025-08-20T19:08:15.6275810Z --23240--     0x7ff81219d264 (aligned_alloc       ) R-> (1017.0) 0x10017fe6e aligned_alloc
2025-08-20T19:08:15.6276210Z --23240--     0x7ff81219d69a (malloc_zone_check   ) R-> (1025.0) 0x100180220 malloc_zone_check
2025-08-20T19:08:15.6276520Z --23240--     0x7ff8121f8ae3 (strrchr             ) R-> (2001.0) 0x100180367 strrchr
2025-08-20T19:08:15.6276880Z --23240--     0x7ff8121ff307 (__strncat_chk       ) R-> (2004.0) 0x10018040f __strncat_chk
2025-08-20T19:08:15.6277230Z --23240--     0x7ff812205729 (__strncpy_chk       ) R-> (2009.0) 0x100180921 __strncpy_chk
2025-08-20T19:08:15.6277580Z --23240--     0x7ff81220664b (__strcpy_chk        ) R-> (2008.0) 0x1001806aa __strcpy_chk
2025-08-20T19:08:15.6278050Z --23240--     0x7ff81230bb60 (operator new(unsigne) R-> (1003.0) 0x10017b033 operator new(unsigned long)
2025-08-20T19:08:15.6278710Z --23240--     0x7ff81230bbbf (operator new(unsigne) R-> (1001.0) 0x10017b67e operator new(unsigned long, std::nothrow_t const&)
2025-08-20T19:08:15.6279180Z --23240--     0x7ff81230bbfb (operator new[](unsig) R-> (1003.0) 0x10017bca5 operator new[](unsigned long)
2025-08-20T19:08:15.6279800Z --23240--     0x7ff81230bc05 (operator new[](unsig) R-> (1001.0) 0x10017c2f0 operator new[](unsigned long, std::nothrow_t const&)
2025-08-20T19:08:15.6280260Z --23240--     0x7ff81230bc29 (operator delete(void) R-> (1005.0) 0x10017cd48 operator delete(void*)
2025-08-20T19:08:15.6280970Z --23240--     0x7ff81230bc33 (operator delete(void) R-> (1005.0) 0x10017d891 operator delete(void*, std::nothrow_t const&)
2025-08-20T19:08:15.6281640Z --23240--     0x7ff81230bc3d (operator delete(void) R-> (1005.0) 0x10017cfff operator delete(void*, unsigned long)
2025-08-20T19:08:15.6282170Z --23240--     0x7ff81230bc47 (operator delete[](vo) R-> (1005.0) 0x10017de10 operator delete[](void*)
2025-08-20T19:08:15.6282890Z --23240--     0x7ff81230bc51 (operator delete[](vo) R-> (1005.0) 0x10017e959 operator delete[](void*, std::nothrow_t const&)
2025-08-20T19:08:15.6283730Z --23240--     0x7ff81230bc5b (operator delete[](vo) R-> (1005.0) 0x10017e0c7 operator delete[](void*, unsigned long)
2025-08-20T19:08:15.6284450Z --23240--     0x7ff81230bc65 (operator new(unsigne) R-> (1003.0) 0x10017b321 operator new(unsigned long, std::align_val_t)
2025-08-20T19:08:15.6285330Z --23240--     0x7ff81230bd0f (operator new(unsigne) R-> (1001.0) 0x10017b94c operator new(unsigned long, std::align_val_t, std::nothrow_t const&)
2025-08-20T19:08:15.6286050Z --23240--     0x7ff81230bd33 (operator new[](unsig) R-> (1003.0) 0x10017bf93 operator new[](unsigned long, std::align_val_t)
2025-08-20T19:08:15.6287160Z --23240--     0x7ff81230bd3d (operator new[](unsig) R-> (1001.0) 0x10017c5be operator new[](unsigned long, std::align_val_t, std::nothrow_t const&)
2025-08-20T19:08:15.6287840Z --23240--     0x7ff81230bd61 (operator delete(void) R-> (1005.0) 0x10017d2d8 operator delete(void*, std::align_val_t)
2025-08-20T19:08:15.6288680Z --23240--     0x7ff81230bd6b (operator delete(void) R-> (1005.0) 0x10017db48 operator delete(void*, std::align_val_t, std::nothrow_t const&)
2025-08-20T19:08:15.6289480Z --23240--     0x7ff81230bd75 (operator delete(void) R-> (1005.0) 0x10017d5b9 operator delete(void*, unsigned long, std::align_val_t)
2025-08-20T19:08:15.6290160Z --23240--     0x7ff81230bd82 (operator delete[](vo) R-> (1005.0) 0x10017e3a0 operator delete[](void*, std::align_val_t)
2025-08-20T19:08:15.6290930Z --23240--     0x7ff81230bd8c (operator delete[](vo) R-> (1005.0) 0x10017ec10 operator delete[](void*, std::align_val_t, std::nothrow_t const&)
2025-08-20T19:08:15.6291670Z --23240--     0x7ff81230bd96 (operator delete[](vo) R-> (1005.0) 0x10017e681 operator delete[](void*, unsigned long, std::align_val_t)
2025-08-20T19:08:15.6292000Z --23240-- >>

This has the line:

2025-08-20T19:08:15.6207770Z --23240--      libsystem_platform.dylib  _platform_memcmp               RL-> (2019.0) 0x100181161

Full logs here: https://github.com/real-or-random/secp256k1/commit/ccb5c7b511eb0eef031d8fc2d232fc0f6eef418f/checks/48521111402/logs

real-or-random avatar Aug 20 '25 19:08 real-or-random

Thanks for this. It does confirm that while redirections exist (the line you found), they aren't being used.

I don't know why, from my limited experience dealing with this, the issue was mostly Apple adding new malloc entrypoints (like the malloc_type_* functions) or Valgrind failing to parse the symbol names and thus not being able to apply redirections. However redirections are working...

The way I debug this is usually by running Valgrind with an excruciating level of detail, opening all dylibs in a disassembler to check what is the exact path the function used to get to that function and see why libplatform_malloc.dylib is not in the chain. I won't make you do that and will try it through GHA like you do, hopefully that will be enough.

LouisBrunner avatar Aug 20 '25 23:08 LouisBrunner

Here's a rather minimal test case (recovery.c):

Thanks a lot for all these details!

Is this enough to produce a suppression rule? Or, if it's too vague, do you have machines to isolate this further?

We can but I am a bit worried it might hide actual issues. Here is a potential suppression:

{
   DYLDCacheCond
   Memcheck:Cond
   obj:/dev/macos/internals/[shared pmap]
   ...
}

{
   DYLDCacheValue8
   Memcheck:Value8
   obj:/dev/macos/internals/[shared pmap]
   ...
}

I also think that these suppressions would be excessively broad.

paulfloyd avatar Aug 21 '25 10:08 paulfloyd

I won't make you do that and will try it through GHA like you do, hopefully that will be enough.

For what it's worth, some reverse shell for GHA like https://github.com/mxschmitt/action-tmate will probably make this much easier.

real-or-random avatar Aug 21 '25 12:08 real-or-random

@real-or-random Could you give the branch feat/bug-135 a try?

LouisBrunner avatar Aug 21 '25 17:08 LouisBrunner

No luck, see https://github.com/real-or-random/secp256k1/actions/runs/17148869882/job/48650423686.

I had a look at your GHA runs here (https://github.com/LouisBrunner/valgrind-macos/actions). The "tell me what you think" run has the right REDIR: 🎉

2025-08-21T14:04:40.3398110Z --53321-- REDIR: 0x7ff8184805de (libsystem_platform.dylib:_platform_memcmp) redirected to 0x1001831a0 (_platform_memcmp)

But the "better" run doesn't have it. The difference is simply https://github.com/LouisBrunner/valgrind-macos/commit/e2b8a620aa6ddb01faf9cc476107bf55af7dff57. Perhaps there's something wrong with the if (is_dynamic)?

real-or-random avatar Aug 22 '25 08:08 real-or-random

Interesting, let me look into it.

When you have the redir, does your test run correctly?

LouisBrunner avatar Aug 22 '25 11:08 LouisBrunner

Turns out that dynamic field is never used on that struct (I confused ExeInfo and IICreateImageInfo as they are used together in VG_(ii_create_image) 🤦‍♀️ ).

I pushed a new commit on that branch with a fix, can you give it a try?

LouisBrunner avatar Aug 22 '25 11:08 LouisBrunner

I pushed a new commit on that branch with a fix, can you give it a try?

[...]
2025-08-22T11:53:18.6631660Z --65688-- REDIR: 0x7ff8081a05de (libsystem_platform.dylib:_platform_memcmp) redirected to 0x1001831a0 (_platform_memcmp)
2025-08-22T11:53:18.6632060Z ==65688== Jump to the invalid address stated on the next line
2025-08-22T11:53:18.6632380Z ==65688==    at 0x0: ???
2025-08-22T11:53:18.6632620Z ==65688==    by 0x100012417: (below main) (in /usr/lib/dyld)
2025-08-22T11:53:18.6632950Z ==65688==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
2025-08-22T11:53:18.6633070Z ==65688== 
2025-08-22T11:53:18.6633180Z ==65688== 
2025-08-22T11:53:18.6633560Z ==65688== Process terminating with default action of signal 11 (SIGSEGV)
2025-08-22T11:53:18.6633840Z ==65688==  Bad permissions for mapped region at address 0x0
2025-08-22T11:53:18.6633970Z ==65688==    at 0x0: ???
2025-08-22T11:53:18.6634200Z ==65688==    by 0x100012417: (below main) (in /usr/lib/dyld)
2025-08-22T11:53:18.6634330Z ==65688== 
2025-08-22T11:53:18.6634470Z ==65688== HEAP SUMMARY:
2025-08-22T11:53:18.6634670Z ==65688==     in use at exit: 8,589 bytes in 174 blocks
2025-08-22T11:53:18.6635000Z ==65688==   total heap usage: 184 allocs, 10 frees, 9,500 bytes allocated
2025-08-22T11:53:18.6635120Z ==65688== 
2025-08-22T11:53:18.6635260Z ==65688== LEAK SUMMARY:
2025-08-22T11:53:18.6635470Z ==65688==    definitely lost: 4,288 bytes in 134 blocks
2025-08-22T11:53:18.6635670Z ==65688==    indirectly lost: 0 bytes in 0 blocks
2025-08-22T11:53:18.6635870Z ==65688==      possibly lost: 576 bytes in 2 blocks
2025-08-22T11:53:18.6636270Z ==65688==    still reachable: 3,725 bytes in 38 blocks
2025-08-22T11:53:18.6636640Z ==65688==         suppressed: 0 bytes in 0 blocks
2025-08-22T11:53:18.6637150Z ==65688== Rerun with --leak-check=full to see details of leaked memory
2025-08-22T11:53:18.6637350Z ==65688== 
2025-08-22T11:53:18.6637830Z ==65688== For lists of detected and suppressed errors, rerun with: -s
2025-08-22T11:53:18.6638320Z ==65688== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 126 from 37)

Well, I guess that's progress?

Your "tell me what you think" build had the same error (with more detailed logs) but I hoped it was caused by some debugging stuff.

real-or-random avatar Aug 22 '25 12:08 real-or-random

Your "tell me what you think" build had the same error (with more detailed logs) but I hoped it was caused by some debugging stuff.

I hoped the same. 😬

Well, back to the drawing board, I'll chime in if I make any progress with this.

LouisBrunner avatar Aug 22 '25 12:08 LouisBrunner

Making a note here so I don't forget.

What is happening is that Valgrind is replacing libsystem_platform's __platform_memcmp but that's not the actual function performing the comparison but the one doing the dispatching between __platform_memcmp$VARIANT$NoOverread and __platform_memcmp$VARIANT$Base. More specifically, it is supposed to return the address of which variant to use. As your memcmp returns 0, libsystem_platform thinks that's the address of the variant to call and just jumps there, crashing the program.

I have actually seen this issue before with Valgrind but I can't recall when/where so I can't recall how I got around to it. We could of course redir the variants instead but that seems like a losing battle (need to track down which variant exist for each CPU/version combo, might even change with minor/patch releases) and we avoided it so far, so let's continue. Of course, if we could simply redir the function doing the dispatch itself, that would be great, unfortunately it has its symbol stripped (Valgrind identify it as _os_semaphore_wait.cold.1+116).

I will see if I can find a way to fix this without introducing hundreds of new redirs.

This is on macOS 13.7.6 22H625.

@josibake couldn't reproduce this on real x86_64 machine with Sequoia 15, and we've never seen it on ARM64 (also 15).

So this seems to be restricted to

* macOS < 15, maybe < 14

* maybe x86_64

Another note, I just reproduced this on my Intel Mac running 15.0.

LouisBrunner avatar Aug 22 '25 18:08 LouisBrunner

Making a note here so I don't forget.

What is happening is that Valgrind is replacing libsystem_platform's __platform_memcmp but that's not the actual function performing the comparison but the one doing the dispatching between __platform_memcmp$VARIANT$NoOverread and __platform_memcmp$VARIANT$Base. More specifically, it is supposed to return the address of which variant to use. As your memcmp returns 0, libsystem_platform thinks that's the address of the variant to call and just jumps there, crashing the program.

That sounds a bit like "ifunc" on Linux and FreeBSD. That also crashes if the ifunc fails to resolve the function :-)

paulfloyd avatar Aug 22 '25 19:08 paulfloyd

Couldn't we redirect __platform_memcmp to a constant function that returns the address of Valgrinds replacement?


I have actually seen this issue before with Valgrind but I can't recall when/where so I can't recall how I got around to it.

Maybe grep for $VARIANT$? https://github.com/LouisBrunner/valgrind-macos/blob/62e094295f597ab966c58cd3b3cc5b5864b3a3f0/shared/vg_replace_strmem.c#L1015-L1020


We could of course redir the variants instead but that seems like a losing battle (need to track down which variant exist for each CPU/version combo, might even change with minor/patch releases) and we avoided it so far, so let's continue.

Sure that has was avoided so far?

https://github.com/LouisBrunner/valgrind-macos/blob/62e094295f597ab966c58cd3b3cc5b5864b3a3f0/shared/vg_replace_strmem.c#L1061-L1070

This one doesn't seem like a losing battle. There's a similar one for memmove.


Another note, I just reproduced this on my Intel Mac running 15.0.

Let me change the title...

real-or-random avatar Aug 23 '25 12:08 real-or-random

Couldn't we redirect __platform_memcmp to a constant function that returns the address of Valgrinds replacement?

That sounds a bit like "ifunc" on Linux and FreeBSD. That also crashes if the ifunc fails to resolve the function :-)

Seems like it's doable but I am not exactly sure how that's done. @paulfloyd Is that doable in a similar way to how vg_replace_strmem.c works or only from a Valgrind client?

https://github.com/LouisBrunner/valgrind-macos/blob/62e094295f597ab966c58cd3b3cc5b5864b3a3f0/shared/vg_replace_strmem.c#L1015-L1020

Ah yes, I did it myself, exactly.

This one doesn't seem like a losing battle. There's a similar one for memmove.

From my POV it is, because either we need to disassemble all versions of libsystem_platform (and its friends) on all archs to make sure we aren't missing a variant, ending up with a fairly complicated compatibility table implemented as ifdef. If we miss one, then we have to wait for someone to tell us (like you did) otherwise Valgrind just reports false positives without any hint that a redir was missed. Alas, that's the path Valgrind has taken so I guess that's how we will do it, but I wouldn't call that sturdy.

Anyway, can you give the PR another try? My test branch seems happy (https://github.com/LouisBrunner/valgrind-macos/actions/runs/17176549660/job/48733219108), same thing for my local testing.

LouisBrunner avatar Aug 23 '25 14:08 LouisBrunner

Couldn't we redirect __platform_memcmp to a constant function that returns the address of Valgrinds replacement?

That sounds a bit like "ifunc" on Linux and FreeBSD. That also crashes if the ifunc fails to resolve the function :-)

Seems like it's doable but I am not exactly sure how that's done. @paulfloyd Is that doable in a similar way to how vg_replace_strmem.c works or only from a Valgrind client?

For ELF the key to this is

void * VG_NOTIFY_ON_LOAD(ifunc_wrapper) (void);

This is a general redirect for ifunc functions. When an ifunc needs to run, this runs instead. It just runs the original ifunc function natively and stores the returned function pointer, Valgrind will contnue to execute the returned pointer.

The other part is that the returned pointer will correspond do some optimized str* or mem* function. Here the regular redirection mechanism will be used - the address will correspond to one of the versions in 'vg_replace_strmem.c'.

I don't know exactly how macOS is doing this dynamic resolution, but it does look similar.

paulfloyd avatar Aug 23 '25 19:08 paulfloyd

This one doesn't seem like a losing battle. There's a similar one for memmove.

From my POV it is, because either we need to disassemble all versions of libsystem_platform (and its friends) on all archs to make sure we aren't missing a variant, ending up with a fairly complicated compatibility table implemented as ifdef. If we miss one, then we have to wait for someone to tell us (like you did) otherwise Valgrind just reports false positives without any hint that a redir was missed. Alas, that's the path Valgrind has taken so I guess that's how we will do it, but I wouldn't call that sturdy.

My thinking was that if this has been done in the past, it's not the end of the world to add more cases. But sure, I fully agree that it's not a great strategy at all.

Let me use this opportunity to say a big thanks for the continued maintenance of this project! This issue was a deep rabbit hole...

Anyway, can you give the PR another try? My test branch seems happy (LouisBrunner/valgrind-macos/actions/runs/17176549660/job/48733219108), same thing for my local testing.

Yes, this does the job! (https://github.com/real-or-random/secp256k1/actions/runs/17154419146/job/48755659500)

The other part is that the returned pointer will correspond do some optimized str* or mem* function. Here the regular redirection mechanism will be used - the address will correspond to one of the versions in 'vg_replace_strmem.c'.

Hm, okay, but if these individual redirections will still be necessary, then VG_NOTIFY_ON_LOAD won't be very helpful (as far as I understand). Why is it necessary on Linux? Or, in other words, what goes wrong without it? (Jumping to addresses returned by functions is something that Valgrind should understand without tricks?)

real-or-random avatar Aug 24 '25 08:08 real-or-random

Let me use this opportunity to say a big thanks for the continued maintenance of this project! This issue was a deep rabbit hole...

No worries at all, happy to help!

Yes, this does the job! (https://github.com/real-or-random/secp256k1/actions/runs/17154419146/job/48755659500)

Merged in main, thanks for your help tracking this down. If you find any other issue, don't hesitate to raise them. 😃

LouisBrunner avatar Aug 24 '25 13:08 LouisBrunner

The other part is that the returned pointer will correspond do some optimized str* or mem* function. Here the regular redirection mechanism will be used - the address will correspond to one of the versions in 'vg_replace_strmem.c'.

Hm, okay, but if these individual redirections will still be necessary, then VG_NOTIFY_ON_LOAD won't be very helpful (as far as I understand). Why is it necessary on Linux? Or, in other words, what goes wrong without it? (Jumping to addresses returned by functions is something that Valgrind should understand without tricks?)

This was all done a long time ago, before I started working on Valgrind. Here is the bugzilla item that describes the problem.

https://bugs.kde.org/show_bug.cgi?id=206013

I don't fully understand why it poses a problem for Valgrind.

paulfloyd avatar Aug 24 '25 19:08 paulfloyd

This was all done a long time ago, before I started working on Valgrind. Here is the bugzilla item that describes the problem.

bugs.kde.org/show_bug.cgi?id=206013

Okay, but after skimming through this and the applied patch, this really sounds like VG_NOTIFY_ON_LOAD could be useful here, too.

real-or-random avatar Aug 25 '25 07:08 real-or-random