I'm attempting to compile Wireshark from the GitHub repo on macOS Sierra using MacPorts. I know there's a macosx-setup.sh
script for installing all the dependencies, but I'd rather not go this route since I have my dependencies fulfilled by MacPorts and I don't want duplicates strewn around my system. I can build and run Wireshark but none of the plugins load. They each fail with an error like the following:
Couldn't load module /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/ethercat.so: dlopen(/Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/ethercat.so, 2): initializer function 0x10fd09b92 not in mapped image for /opt/local/lib/libgpg-error.0.dylib
The initializer function address is different with each build of Wireshark that I make. The steps I use for building are:
mkdir build
cd build
cmake ..
make
make app_bundle
CMake doesn't report any required dependencies missing, and GPG itself is discovered as follows:
-- Found GCRYPT: /opt/local/lib/libgcrypt.dylib (found suitable version "1.7.6", minimum required is "1.4.2")
-- GCRYPT FOUND
-- GCRYPT includes: /opt/local/include
-- GCRYPT libs: /opt/local/lib/libgcrypt.dylib;/opt/local/lib/libgpg-error.dylib
I notice that libgpg-error.0.dylib
in the build output differs from the one MacPorts provides.
diff /opt/local/lib/libgpg-error.0.dylib /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/Frameworks/libgpg-error.0.dylib
Binary files /opt/local/lib/libgpg-error.0.dylib and /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/Frameworks/libgpg-error.0.dylib differ
It appears that some paths in the Application-local dylib are being remapped in the build process (from otool -l
):
Load command 10
cmd LC_LOAD_DYLIB
cmdsize 72
name @executable_path/../Frameworks/libintl.8.dylib (offset 24)
It seems to me, that the Application-local dylib (not the MacPorts one) should be loading. I don't have any of these environment variables set:
$DYLD_FRAMEWORK_PATH
$DYLD_FALLBACK_FRAMEWORK_PATH
$DYLD_VERSIONED_FRAMEWORK_PATH
$DYLD_LIBRARY_PATH
$DYLD_FALLBACK_LIBRARY_PATH
$DYLD_VERSIONED_LIBRARY_PATH
$DYLD_ROOT_PATH
$DYLD_INSERT_LIBRARIES
I would expect Wireshark's dlopen
call to first look in the application package before searching the system. Has anyone else built on a MacPorts system and run into this?
EDIT:
I did some tracking of the module load process by turning on some DYLD environment variables. I just looked at the docsis.so
plugin.
The applicable parts of the debug trace are as follows:
dyld: Main executable mapped /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/MacOS/Wireshark
__PAGEZERO at 0x00000000->0x100000000
__TEXT at 0x10636E000->0x1069B6000
__DATA at 0x1069B6000->0x106A1E000
__LINKEDIT at 0x106A1E000->0x106B7B9F8
dyld: loaded: /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/MacOS/Wireshark
dyld: re-using existing development shared cache mapping 0x7FFF8A27D000->0x7FFFA5009FFF read execute init=5, max=5 0x7FFFA900A000->0x7FFFADBE4FFF read write init=3, max=3 0x7FFFB1BE5000->0x7FFFB915CFFF read init=1, max=1 0x7FFF9EEE0000->0x7FFF9F3C0000 (code signature)
This is where we're loading all the shared libraries on startup. Notice that libgpg-error.0.dylib
is first loaded from the application package.
dyld: Mapping /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/MacOS/../Frameworks/libgpg-error.0.dylib
__TEXT at 0x10A4BA000->0x10A4C7FFF with permissions r.x
__DATA at 0x10A4C8000->0x10A4C8FFF with permissions rw.
__LINKEDIT at 0x10A4C9000->0x10A4CD1E7 with permissions r..
__DATA prefetching 0x10A4C8000 -> 0x10A4C8FFF
dyld: loaded: /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/MacOS/../Frameworks/libgpg-error.0.dylib
Here's the binding of the initialization function:
dyld: bind: libgpg-error.0.dylib:0x10A4C84B8 = libgpg-error.0.dylib:_gpg_err_init, *0x10A4C84B8 = 0x10A4C3B92
Then, it's called.
dyld: calling initializer function 0x10a4c3b92 in /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/MacOS/../Frameworks/libgpg-error.0.dylib
This looks like a lazy bind of the initialization function again, but it starts with two underscores.
dyld: lazy bind: libgpg-error.0.dylib:0x10A4C8078 = libgpg-error.0.dylib:__gpg_err_init, *0x10A4C8078 = 0x10A4BC345
Now the docsis plugin is loaded.
dlopen(/Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/docsis.so, 0x00000002)
dyld: Mapping /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/docsis.so
__TEXT at 0x114D47000->0x114D6DFFF with permissions r.x
__DATA at 0x114D6E000->0x114D84FFF with permissions rw.
__LINKEDIT at 0x114D85000->0x114DABBDB with permissions r..
dyld: loaded: /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/docsis.so
Then libgpg-error.0.dylib
is loaded again! But this time it's from MacPorts and it's going into a different part of memory.
dyld: Mapping /opt/local/lib/libgpg-error.0.dylib
__TEXT at 0x114F68000->0x114F75FFF with permissions r.x
__DATA at 0x114F76000->0x114F76FFF with permissions rw.
__LINKEDIT at 0x114F77000->0x114F7BA37 with permissions r..
dyld: loaded: /opt/local/lib/libgpg-error.0.dylib
The initialization function is bound again. It's bound to the same address as before, but this time from the memory location holding the MacPorts version of the library.
dyld: bind: libgpg-error.0.dylib:0x114F764B8 = libgpg-error.0.dylib:_gpg_err_init, *0x114F764B8 = 0x10A4C3B92
Then the lazy bind of the init function with two underscores again.
dyld: forced lazy bind: libgpg-error.0.dylib:0x114F76078 = libgpg-error.0.dylib:__gpg_err_init, *0x114F76078 = 0x10A4BC345
The glib initializer is called, and then docsis is considered unused? Huh.
dyld: calling initializer function 0x114dd66ae in /opt/local/lib/libglib-2.0.0.dylib
dlclose(), found unused image 0x7fa2d2c1f610 docsis.so
dlclose(), deleting 0x7fa2d2c1f610 docsis.so
dyld: unloaded: /Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/docsis.so
Then one (the MacPorts one, I think) of the gpg lib's images is considered unused.
dlclose(), found unused image 0x60000015c1a0 libgpg-error.0.dylib
It's unloaded.
dlclose(), deleting 0x60000015c1a0 libgpg-error.0.dylib
dyld: unloaded: /opt/local/lib/libgpg-error.0.dylib
Now DYLD spits out the error about not finding the initialization function for gpg.
dlopen() failed, error: 'dlopen(/Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/docsis.so, 2): initializer function 0x10a4c3b92 not in mapped image for /opt/local/lib/libgpg-error.0.dylib
'
dyld: lazy bind: libgmodule-2.0.0.dylib:0x10B78E0C8 = libdyld.dylib:_dlerror, *0x10B78E0C8 = 0x7FFFA4D89907
dlerror()
It makes sense that I'm having this problem given the output of otool
on Wireshark versus the docsis plugin:
hostname:~ username$ otool -L ~/src/github/wireshark/build/run/Wireshark.app/Contents/MacOS/Wireshark
/Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/MacOS/Wireshark:
@executable_path/../Frameworks/libgpg-error.0.dylib (compatibility version 22.0.0, current version 22.0.0)
hostname:~ username$ otool -L ~/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/docsis.so
/Users/username/src/github/wireshark/build/run/Wireshark.app/Contents/PlugIns/wireshark/docsis.so:
/opt/local/lib/libgpg-error.0.dylib (compatibility version 22.0.0, current version 22.0.0)
However, I’m not sure why the docsis plugin looks in one location for libgpg while the Wireshark binary looks elsewhere.