Valgrind macOs and error Syscall param msg->desc.p

2019-04-04 14:23发布

问题:

I tried to run valgrind 3.13 and 3.14 (on macOs 10.12.6) in very simple project but I got strange error who I never got in my linux before.

  1. Very simple C program main.c:

    int main() {
        return (0);
    }
    
  2. Compilation with cc:

    $> cc main.c
    
  3. Run my simple program with valgrind:

    $> valgrind ./a.out
    
  4. Output of valgrind:

    ==12768== Memcheck, a memory error detector
    ==12768== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==12768== Using Valgrind-3.14.0.SVN and LibVEX; rerun with -h for copyright info
    ==12768== Command: ./a.out
    ==12768==
    ==12768== Syscall param msg->desc.port.name points to uninitialised byte(s)
    ==12768==    at 0x10049434A: mach_msg_trap (in /usr/lib/system/libsystem_kernel.dylib)
    ==12768==    by 0x100493796: mach_msg (in /usr/lib/system/libsystem_kernel.dylib)
    ==12768==    by 0x10048D485: task_set_special_port (in /usr/lib/system/libsystem_kernel.dylib)
    ==12768==    by 0x10062910E: _os_trace_create_debug_control_port (in /usr/lib/system/libsystem_trace.dylib)
    ==12768==    by 0x100629458: _libtrace_init (in /usr/lib/system/libsystem_trace.dylib)
    ==12768==    by 0x1001599DF: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
    ==12768==    by 0x100017A1A: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
    ==12768==    by 0x100017C1D: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
    ==12768==    by 0x1000134A9: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
    ==12768==    by 0x100013440: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
    ==12768==    by 0x100012523: ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
    ==12768==    by 0x1000125B8: ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
    ==12768==  Address 0x10488ac6c is on thread 1's stack
    ==12768==  in frame #2, created by task_set_special_port (???:)
    ==12768==  Uninitialised value was created by a stack allocation
    ==12768==    at 0x1006290A6: _os_trace_create_debug_control_port (in /usr/lib/system/libsystem_trace.dylib)
    ==12768==
    ==12768==
    ==12768== HEAP SUMMARY:
    ==12768==     in use at exit: 18,144 bytes in 162 blocks
    ==12768==   total heap usage: 178 allocs, 16 frees, 24,288 bytes allocated
    ==12768==
    ==12768== LEAK SUMMARY:
    ==12768==    definitely lost: 3,456 bytes in 54 blocks
    ==12768==    indirectly lost: 0 bytes in 0 blocks
    ==12768==      possibly lost: 72 bytes in 3 blocks
    ==12768==    still reachable: 200 bytes in 6 blocks
    ==12768==         suppressed: 14,416 bytes in 99 blocks
    ==12768== Rerun with --leak-check=full to see details of leaked memory
    ==12768==
    ==12768== For counts of detected and suppressed errors, rerun with: -v
    ==12768== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
    

    I do not understand this part of trace:

    ==12768== Syscall param msg->desc.port.name points to uninitialised byte(s)
    ==12768==    at 0x10049434A: mach_msg_trap (in /usr/lib/system/libsystem_kernel.dylib)
    ==12768==    by 0x100493796: mach_msg (in /usr/lib/system/libsystem_kernel.dylib)
    ==12768==    by 0x10048D485: task_set_special_port (in /usr/lib/system/libsystem_kernel.dylib)
    ==12768==    by 0x10062910E: _os_trace_create_debug_control_port (in /usr/lib/system/libsystem_trace.dylib)
    ==12768==    by 0x100629458: _libtrace_init (in /usr/lib/system/libsystem_trace.dylib)
    ==12768==    by 0x1001599DF: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
    ==12768==    by 0x100017A1A: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
    ==12768==    by 0x100017C1D: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
    ==12768==    by 0x1000134A9: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
    ==12768==    by 0x100013440: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
    ==12768==    by 0x100012523: ImageLoader::processInitializers(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
    ==12768==    by 0x1000125B8: ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
    ==12768==  Address 0x10488ac6c is on thread 1's stack
    ==12768==  in frame #2, created by task_set_special_port (???:)
    ==12768==  Uninitialised value was created by a stack allocation
    ==12768==    at 0x1006290A6: _os_trace_create_debug_control_port (in /usr/lib/system/libsystem_trace.dylib)
    

I do not understand why the heap summary is so big (178 allocs, 16 frees, 24,288 bytes allocated) of my simple return(0); program.

回答1:

Valgrind has a system for suppressing errors. Suppression rules are specified in special files, for instance $PREFIX/lib/valgrind/default.supp. Users can create their own rules using the --gen-suppressions=full aid, which will print a suppression rule for each error encountered. The user can then customize it to their own needs.

I did this for the error in question, and it works great! No need to install unstable versions. This is also a good tool in the belt if you run into other reported errors you'd like to ignore.

I saved this file as ~/.valgrind.supp.

# false positive for any executable (it seems)
# macOS 10.12.6
# valgrind 3.13.0
{
    libtrace initialization false positive
    Memcheck:Param
    msg->desc.port.name
    fun:mach_msg_trap
    fun:mach_msg
    fun:task_set_special_port
    fun:_os_trace_create_debug_control_port
    fun:_libtrace_init
}

# starts a comment and {} denote a rule. The first line is the name of the rule. The second one says which tool and error type to suppress. Param means invalid syscall param, and the next line gives the parameter to suppress errors for. The following lines starting with fun: means this suppression rule only applies in mach_msg_trap when called by mach_msg called by task_set_special_port and so on. This way we only suppress the error in this very specific case where Valgrind mistakes libtrace initialization for an error.

Valgrind will use this rule if you supply the argument --suppressions=$HOME/.valgrind.supp on the command line, or put it in $VALGRIND_OPTS or ~/.valgrindrc.

  • Suppressing errors [Valgrind]
  • Setting default options [Valgrind]
  • Writing suppression files [Memcheck]
  • Valgrind Suppression File Howto [wkWiki]


回答2:

I just checked the bug status here and it appears solved, so I just checked out the corresponding commit and compile. It solves the issue of the uninitialised byte(s) but seams to create new problems: unhandled MACH_SEND_TRAILER ?

1) clone master branch

$ git clone git://sourceware.org/git/valgrind.git

2) patch it with the fix:

$ cd valgrind

$ git checkout 128fd6e

3) configure compile and install as usual, instructions here

4) test it with a simple program

$ cd <install-folder>/bin
$ ./valgrind ls -l

==19116== Memcheck, a memory error detector
==19116== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==19116== Using Valgrind-3.14.0.GIT and LibVEX; rerun with -h for copyright info
==19116== Command: ls -l
==19116== 
--19116-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option
--19116-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 2 times)
--19116-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 4 times)
--19116-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 8 times)
total 552
-rwxr-xr-x  1 user  student  41642 Sep 11 15:55 callgrind_annotate
-rwxr-xr-x  1 user  student  12020 Sep 11 15:55 callgrind_control
-rwxr-xr-x  1 user  student  32174 Sep 11 15:55 cg_annotate
-rwxr-xr-x  1 user  student  10422 Sep 11 15:55 cg_diff
-rwxr-xr-x  1 user  student  29964 Sep 11 15:55 cg_merge
-rwxr-xr-x  1 user  student  24402 Sep 11 15:55 ms_print
-rwxr-xr-x  1 user  student  24468 Sep 11 15:55 valgrind
-rwxr-xr-x  1 user  student  39048 Sep 11 15:55 valgrind-di-server
-rwxr-xr-x  1 user  student  15056 Sep 11 15:55 valgrind-listener
-rwxr-xr-x  1 user  student  40216 Sep 11 15:55 vgdb
==19116== 
==19116== HEAP SUMMARY:
==19116==     in use at exit: 136,779 bytes in 225 blocks
==19116==   total heap usage: 420 allocs, 195 frees, 202,112 bytes allocated
==19116== 
==19116== LEAK SUMMARY:
==19116==    definitely lost: 0 bytes in 0 blocks
==19116==    indirectly lost: 0 bytes in 0 blocks
==19116==      possibly lost: 72 bytes in 3 blocks
==19116==    still reachable: 114,861 bytes in 71 blocks
==19116==         suppressed: 21,846 bytes in 151 blocks
==19116== Rerun with --leak-check=full to see details of leaked memory
==19116== 
==19116== For counts of detected and suppressed errors, rerun with: -v
==19116== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

The same test done on linux ubuntu 16.04, with valgrind 3.11.0 provides a clean output.