Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Failed to build with MUSL target #181

Closed
qjerome opened this issue Aug 29, 2024 · 10 comments
Closed

Failed to build with MUSL target #181

qjerome opened this issue Aug 29, 2024 · 10 comments

Comments

@qjerome
Copy link
Contributor

qjerome commented Aug 29, 2024

The project fails to build (at least for me) for MUSL target.

OS: Archlinux

Error

  = note: /usr/bin/ld: /usr/lib/libm-2.40.a(s_truncf.o): warning: relocation against `_dl_x86_cpu_features' in read-only section `.text'
          /usr/bin/ld: /usr/lib/libm-2.40.a(w_log10.o): in function `__log10':
          (.text+0x1f): undefined reference to `errno'
          /usr/bin/ld: /usr/lib/libm-2.40.a(e_log2.o): in function `__log2_ifunc':
          (.text+0x2fd): undefined reference to `_dl_x86_cpu_features'
          /usr/bin/ld: (.text+0x306): undefined reference to `_dl_x86_cpu_features'
          /usr/bin/ld: /usr/lib/libm-2.40.a(e_log.o): in function `__ieee754_log_ifunc':
          (.text+0x2c6): undefined reference to `_dl_x86_cpu_features'
          /usr/bin/ld: (.text+0x2d1): undefined reference to `_dl_x86_cpu_features'
          /usr/bin/ld: (.text+0x2da): undefined reference to `_dl_x86_cpu_features'
          /usr/bin/ld: /usr/lib/libm-2.40.a(s_ceil.o):(.text+0x6): more undefined references to `_dl_x86_cpu_features' follow
          /usr/bin/ld: /usr/lib/libm-2.40.a(math_err.o): in function `with_errno':
          (.text+0x3): undefined reference to `errno'
          /usr/bin/ld: read-only segment has dynamic relocations
          collect2: error: ld returned 1 exit status
          
  = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)

Expected behaviour

Being able to compile with MUSL target to create portable binaries (at least on Linux).

Replicate the issue

# assuming you are in yara-x project dir
cargo build --target x86_64-unknown-linux-musl --bins
@plusvic
Copy link
Member

plusvic commented Aug 29, 2024

The problem here is that the x86_64-unknown-linux-musl target tries to link the C runtime statically by default. But for some reason the /usr/lib/libm-2.40.a static library contains references to symbols _dl_x86_cpu_features and errno, which are not found by the linker. These symbols are normally provided by glibc. So, it looks like the linker is trying to use the glibc's version of libm instead of the musl's version of libm.

In the wasmtime project they have the same issue: bytecodealliance/wasmtime#8898. Given that YARA-X depends on wasmtime, the root cause is probably the same.

You can force the linker to link the C runtime dynamically:

RUSTFLAGS='-C target-feature=-crt-static' cargo build --target x86_64-unknown-linux-musl --bins

This produces a binary without issues, but of course, the binary will be dynamically linked to glibc's versions of libm and libc, and that's precisely what we don't want.

@plusvic
Copy link
Member

plusvic commented Aug 29, 2024

In bytecodealliance/wasmtime#8898 (comment) they propose setting this environment variable:

CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=musl-gcc

And in fact, it worked for me. Can you try that?

The problem seems to be that cargo is invoking the host default linker, instead of using musl-gcc. This also explains why they also propose using an Alpine Linux host as a workaround. In Alpine Linux the default linker already links against musl instead of glibc.

@plusvic
Copy link
Member

plusvic commented Aug 29, 2024

Unfortunately the produced binary causes a SIGSEGV during the startup. The issue looks similar to this:
rust-lang/rust#81987

@plusvic
Copy link
Member

plusvic commented Aug 29, 2024

By setting this other environment variable I'm able to produce a binary that works:

RUSTFLAGS='-C relocation-model=static'

However, it produces a nasty error message:

libunwind: __unw_add_dynamic_fde: bad fde: FDE is really a CIE

Except for this message everything seems to work fine.

@qjerome
Copy link
Contributor Author

qjerome commented Aug 29, 2024

Thank you very much for your help, indeed it seems to work. Yet I'd like to get rid of that error if possible as the next step for we would be to try to integrate yara-x into my project.

Maybe a stupid question: what is the technical reason justifying the use of wasmtime ?

@plusvic
Copy link
Member

plusvic commented Aug 29, 2024

The reason is mainly performance. The boolean conditions in YARA rules are transformed into WASM code, which in turns is transformed into native code by wasmtime. Conditions that rely on heavy loops are much faster with this approach.

@qjerome
Copy link
Contributor Author

qjerome commented Aug 29, 2024

According to bytecodealliance/wasmtime#8897 it doesn't seem obvious to remove that error message ...

@plusvic
Copy link
Member

plusvic commented Aug 29, 2024

After 6953528 everything should be fine, please check.

@plusvic
Copy link
Member

plusvic commented Aug 29, 2024

BTW, the pre-built Linux binaries distributed with each release are statically linked and should be portable between different Linux systems, they don't rely on the system's libc.

These files are built with:

RUSTFLAGS= "-C target-feature=+crt-static" cargo build --bin yr --profile release-lto

With -C target-feature=+crt-static you force glibc to be linked statically into the binary. So, if the only thing you want is a statically linked file you don't really need musl. If you want to use musl for some other reason that's fine, and it's great to have someone testing it.

@qjerome
Copy link
Contributor Author

qjerome commented Sep 2, 2024

This solution works when building yara-x binary yet it doesn't when building a project embedding yara-x library in a project needing MUSL build. The linker settings and the rustflags need to be set anyway when building the project (using yara-x library).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants