Cross-compilation linux -> windows pthread linking issues

Hi people,

I'm trying to cross-compile a crate of mine from my x86_64 linux to i686 windows using the target i686-pc-windows-gnu.

The line I'm using is
SODIUM_STATIC="foo" PKG_CONFIG_ALLOW_CROSS=1 cargo rustc --target "i686-pc-windows-gnu", but I've also tried variations like
SODIUM_STATIC="foo" PKG_CONFIG_ALLOW_CROSS=1 cargo rustc --target "i686-pc-windows-gnu" -- -C panic=abort after seeing https://github.com/rust-lang/rust/issues/32859 this thread, but none of the solutions proposed worked: I keep on seeing this linking error:

/usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to "pthread_mutex_unlock" (full trace below)

error: linking with `/usr/bin/i686-w64-mingw32-gcc` failed: exit code: 1
  |
  = note: "/usr/bin/i686-w64-mingw32-gcc" "-fno-use-linker-plugin" "-Wl,--nxcompat" "-Wl,--large-address-aware" "/home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsbegin.o" "-L" "/home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib" "/home/polochon/Documents/Programming/S\xc3\xa9cu
(..) "/home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/liballoc-f3d4a85cc31b7146.rlib" "/home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/librustc_std_workspace_core-a29a98f36367f5b6.rlib" "/home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcore-282891e49fb5727f.rlib" "-Wl,--end-group" "/home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libcompiler_builtins-24e4a79011a169a0.rlib" "-Wl,-Bdynamic" "-lws2_32" "-lgdi32" "-luser32" "-lcrypt32" "-lws2_32" "-ladvapi32" "-lkernel32" "-lwinapi_advapi32" "-lwinapi_bcrypt" "-lwinapi_cfgmgr32" "-lwinapi_crypt32" "-lwinapi_cryptnet" "-lwinapi_fwpuclnt" "-lwinapi_gdi32" "-lwinapi_kernel32" "-lwinapi_msimg32" "-lwinapi_ncrypt" "-lwinapi_ntdll" "-lwinapi_ole32" "-lwinapi_opengl32" "-lwinapi_shell32" "-lwinapi_user32" "-lwinapi_winspool" "-lwinapi_ws2_32" "-lsodium" "-ladvapi32" "-lws2_32" "-luserenv" "-lmsvcrt" "-lmingwex" "-lmingw32" "-lmsvcrt" "-luser32" "-lkernel32" "-lgcc_eh" "-l:libpthread.a" "-lgcc" "-lmsvcrt" "-lkernel32" "/home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/rsend.o"
  = note: /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_init_function':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:733: undefined reference to `pthread_mutex_init'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_unlock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to `pthread_mutex_unlock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to `pthread_mutex_unlock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_once':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:700: undefined reference to `pthread_once'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_lock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:749: undefined reference to `pthread_mutex_lock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o): in function `_gthread_mutex_unlock':
          /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to `pthread_mutex_unlock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to `pthread_mutex_unlock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to `pthread_mutex_unlock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to `pthread_mutex_unlock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: undefined reference to `pthread_mutex_unlock'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/i686-pc-windows-gnu/lib/libgcc_eh.a(unwind-dw2-fde.o):/build/mingw-w64-gcc/src/build-i686-w64-mingw32/i686-w64-mingw32/libgcc/./gthr-default.h:779: more undefined references to `pthread_mutex_unlock' follow
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error; 9 warnings emitted

error: could not compile `ssh_server`.

To learn more, run the command again with --verbose.

My Cargo.toml looks like this:

[dependencies]    
thrussh = { path = "/home/polochon/Documents/Programming/Rust/thrussh-0.28.0" }    
thrussh-keys = "*"    
futures = "*"    
tokio = "*"    
anyhow = "*"    
env_logger = "*"    
log = "*"    
openssl = { version = "0.10", features = ["vendored"] }    
    
[features]    
default = ["net-tokio"]        
net-tokio = ["tokio/net"]    
    
[target.'cfg(windows)'.dependencies]    
winapi = { version = "0.3", features = ["wincrypt"] }

I have

[target.i686-pc-windows-gnu]    
linker = "/usr/bin/i686-w64-mingw32-gcc"    
ar = "/usr/i686-w64-mingw32/bin/ar" 

in my cargo config, and the mingw compiler has been compiled like this:

Using built-in specs.
COLLECT_GCC=i686-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-w64-mingw32/10.2.0/lto-wrapper
Target: i686-w64-mingw32
Configured with: /build/mingw-w64-gcc/src/gcc/configure --prefix=/usr --libexecdir=/usr/lib --target=i686-w64-mingw32 --with-bugurl=https://bugs.archlinux.org/ --enable-languages=c,lto,c++,ada,objc,obj-c++,fortran --enable-shared --enable-static --enable-threads=posix --enable-fully-dynamic-string --enable-libstdcxx-time=yes --enable-libstdcxx-filesystem-ts=yes --with-system-zlib --enable-cloog-backend=isl --enable-lto --enable-libgomp --disable-multilib --enable-checking=release --disable-sjlj-exceptions --with-dwarf2
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 10.2.0 (GCC) 

I looked around a lot but haven't been able to fix this issue; would anyone have an idea? :slight_smile:

Cheers!

1 Like

Don't use PKG_CONFIG_ALLOW_CROSS=1. pkg-config disables itself during cross-compilation not to make you set a variable, but because it detects it won't work. For pkg-config not to back-stab you during cross-compilation by finding incompatible libraries you would have to create a Windows-specific sysroot first and configure pkg-config's env variables to prevent pkg-config from seeing Linux libraries and only find Windows ones.

Apart from that, you need to have a Windows+MinGW version of libpthread. I don't think Rust comes with one, so you may need to get a mingw installation and extract it from there?

1 Like

Oh, sorry.

I already have mingw-w64-winpthreads, and removing the pkg-config changed the linking error, so I guess that was the problem for that first part. Thanks!

However, now I get a bunch of undefined reference to "__memcpy_chk" with this line:
SODIUM_LIB_DIR=/usr/i686-w64-mingw32/lib SODIUM_STATIC="foo" OPENSSL_STATIC=1 cargo rustc --target "i686-pc-windows-gnu"

  = note: /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/Documents/Programming/Sécu/Pentesting/ssh_payload/target/i686-pc-windows-gnu/debug/deps/libthrussh_libsodium-1c11116f173f0837.rlib(libsodium_la-blake2b-ref.o):(.text+0x4d7): undefined reference to `__memcpy_chk'
          /usr/lib/gcc/i686-w64-mingw32/10.2.0/../../../../i686-w64-mingw32/bin/ld: /home/polochon/Documents/Programming/Sécu/Pentesting/ssh_payload/target/i686-pc-windows-gnu/debug/deps/libthrussh_libsodium-1c11116f173f0837.rlib(libsodium_la-blake2b-ref.o):(.text+0x645): undefined reference to `__memcpy_chk'
          collect2: error: ld returned 1 exit status

From what I've read from various sources, it's due do the fact that these library use stack protection with _FORTIFY_SOURCE, but don't ship the symbols with them, instead relying on the fact that I should link everything with -lssp. (it does compile with this flag enabled with RUSTFLAGS)

This makes me depend on shipping libssp.dll though, and I cannot really do that (I'd need a "fully" static binary). Since I'm providing my own libsodium (apparently there is no way to let rust build it like openssl-sys), I'm wondering at which level this static linking should happen.
Does anyone have had experience with that ? :slight_smile:

Maybe you could fudge it with:

#[no_mangle]
pub extern fn __memcpy_chk(dest: *mut c_void, src: *const c_void, len: usize, destlen: usize) {
   assert!(len <= destlen);
   libc::memcpy(dest, src, len);
}

or try compiling libsodium with the same compiler settings as the rest of the Rust code. Maybe use the cc crate?

Apparently the second problem was a libsodium-thing only (https://github.com/jedisct1/libsodium/issues/962).
I fixed it by using the pre-compiled stable version - it's not the best, but it works.

Sorry for the off-topic, and thanks for the help!
For posterity: the command-line is
SODIUM_LIB_DIR=/path/to/libsodium-win64/lib SODIUM_STATIC="foo" OPENSSL_STATIC=1 cargo rustc --target "x86_64-pc-windows-gnu"

Resolving.