gnome-sdk icon indicating copy to clipboard operation
gnome-sdk copied to clipboard

aarch32, riscv64: undefined symbols: __frexpf, __ldexpf, __frexp, __ldexp

Open nteodosio opened this issue 1 year ago • 6 comments

From Chromium 130 build:

:: [37706/49216] LINK ./generate_colors_info
:: FAILED: generate_colors_info
:: "python3" "../../build/toolchain/gcc_link_wrapper.py" --output="./generate_colors_info" -- /snap/llvm-chromium/current/bin/clang++ -fuse-ld=lld -Wl,--fatal-warnings -Wl,--build-id=sha1 -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--icf=all -Wl,--no-keep-memory -Wl,--color-diagnostics -Wl,--undefined-version --target=arm-linux-gnueabihf -no-canonical-prefixes -Wl,-O2 -Wl,--gc-sections -Wl,-z,defs -Wl,--as-needed -nostdlib++ -rdynamic -pie -Wl,--disable-new-dtags prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcfg_if.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcompiler_builtins.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcore.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libgetopts.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libhashbrown.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libpanic_abort.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libpanic_unwind.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/librustc_demangle.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd_detect.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libtest.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libunicode_width.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libunwind.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libaddr2line.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libadler.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libgimli.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liblibc.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libmemchr.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libminiz_oxide.rlib prebuilt_rustc_sysroot/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libobject.rlib -L/snap/gnome-46-2404-sdk/current/usr/lib/arm-linux-gnueabihf -o "./generate_colors_info" -Wl,--start-group @"./generate_colors_info.rsp" -Wl,--end-group   /snap/llvm-chromium/current/lib/clang/20/lib/armv7-unknown-linux-gnueabihf/libclang_rt.builtins.a -ldl -lpthread -lrt -lgmodule-2.0 -lglib-2.0 -lgobject-2.0 -lgthread-2.0 -latomic -lexpat -lfontconfig -lX11-xcb -lX11 -lxcb -Wl,--start-group obj/third_party/rust/cxx/v1/lib/libcxx_lib.rlib obj/third_party/rust/serde_json_lenient/v0_2/wrapper/libthird_uparty_srust_sserde_ujson_ulenient_sv0_u2_swrapper_cwrapper.rlib obj/third_party/rust/serde/v1/lib/libserde_lib.rlib obj/third_party/rust/serde_json_lenient/v0_2/lib/libserde_json_lenient_lib.rlib obj/third_party/rust/itoa/v1/lib/libitoa_lib.rlib obj/third_party/rust/ryu/v1/lib/libryu_lib.rlib obj/build/rust/chromium_prelude/libchromium.rlib obj/skia/libskia_cbridge_urust_uside.rlib obj/third_party/rust/font_types/v0_6/lib/libfont_types_lib.rlib obj/third_party/rust/bytemuck/v1/lib/libbytemuck_lib.rlib obj/third_party/rust/read_fonts/v0_20/lib/libread_fonts_lib.rlib obj/third_party/rust/skrifa/v0_20/lib/libskrifa_lib.rlib -Wl,--end-group
:: ld.lld: error: undefined symbol: __frexpf
:: >>> referenced by s_cbrtf.o:(__cbrtf) in archive /snap/gnome-46-2404-sdk/current/usr/lib/arm-linux-gnueabihf/libm.a
::
:: ld.lld: error: undefined symbol: __ldexpf
:: >>> referenced by s_cbrtf.o:(__cbrtf) in archive /snap/gnome-46-2404-sdk/current/usr/lib/arm-linux-gnueabihf/libm.a
::
:: ld.lld: error: undefined symbol: __frexp
:: >>> referenced by s_cbrt.o:(__cbrt) in archive /snap/gnome-46-2404-sdk/current/usr/lib/arm-linux-gnueabihf/libm.a
::
:: ld.lld: error: undefined symbol: __ldexp
:: >>> referenced by s_cbrt.o:(__cbrt) in archive /snap/gnome-46-2404-sdk/current/usr/lib/arm-linux-gnueabihf/libm.a
:: clang++: error: linker command failed with exit code 1 (use -v to see invocation)

This does not happen in aarch64 or x64.

nteodosio avatar Sep 18 '24 07:09 nteodosio

When building the gnome-46-2404-sdk snap package for riscv64 the same symbols are missing: https://launchpadlibrarian.net/784922703/buildlog_snap_ubuntu_noble_riscv64_gnome-46-2404-sdk_BUILDING.txt.gz

xypron avatar Mar 28 '25 11:03 xypron

__frexpf, __ldexpf, __frexp, __ldexp are internal symbols of the math.h library.

$ nm /usr/lib/riscv64-linux-gnu/libc.a 2>/dev/null | grep -e '__frexpf$' -e '__ldexpf$' -e '__frexp$' -e '__ldexp$'
0000000000000000 T __ldexp
0000000000000000 T __frexp
0000000000000000 T __ldexpf
0000000000000000 T __frexpf

xypron avatar Mar 28 '25 11:03 xypron

Isn't that supposed to be in the base snap? Are we barking up the wrong tree?

nteodosio avatar Mar 28 '25 13:03 nteodosio

In the snapcraft debug session I tried to build

#include <stdio.h>
#include <math.h>

int main()
{
        float a = 8;
        float b;

        b = cbrtf(a);

        printf("%f = %f ^ (1 / 3)\n", b, a);

        return 0;
}

against libm.a:

# gcc test.c /usr/lib/riscv64-linux-gnu/libm.a -o test
/usr/bin/ld: /usr/lib/riscv64-linux-gnu/libm.a(s_cbrtf.o): in function `__cbrtf':
(.text+0x2e): undefined reference to `__frexpf'
/usr/bin/ld: (.text+0xe0): undefined reference to `__ldexpf'
collect2: error: ld returned 1 exit status

This looks like the error we see when building gtk4.

The following statements both work correctly:

gcc test.c /usr/lib/riscv64-linux-gnu/libm.a /usr/lib/riscv64-linux-gnu/libc.a -o test
gcc test.c -m -o test

xypron avatar Mar 31 '25 20:03 xypron

Summary

I couldn't get my hands on a Risc-V or ARM machine and full emulation in my x64 was way too slow. But I managed to figure at least part of the problem and get a successful build:

Armhf (done): https://launchpad.net/~nteodosio/+snap/46-sdk-fuse-mc/+build/2787414 Riscv (ongoing!): https://launchpad.net/~nteodosio/+snap/46-sdk-fuse-mc/+build/2787504

By removing staged lib[cm] from Libtool part.

Analysis

The failed logs say

:: /build/gnome-46-2404-sdk/stage/usr/bin/ld: /build/gnome-46-2404-sdk/stage/usr/lib/riscv64-linux-gnu/libm.a(s_cbrtf.o): in function `__cbrtf':

This libm from a stage path is suspicious. So I introduced a find for debugging in the Snapcraft build, and found its origin:

:: + find / -name 'libc[-.]*' -o -name 'libm[-.]*'
:: /build/gnome-46-2404-sdk/parts/libtool/install/usr/lib/arm-linux-gnueabihf/libm.so
:: /build/gnome-46-2404-sdk/parts/libtool/install/usr/lib/arm-linux-gnueabihf/libc.a
:: /build/gnome-46-2404-sdk/parts/libtool/install/usr/lib/arm-linux-gnueabihf/libm.a
:: /build/gnome-46-2404-sdk/parts/libtool/install/usr/lib/arm-linux-gnueabihf/libc.so
[--snip--]
:: /build/gnome-46-2404-sdk/stage/usr/lib/arm-linux-gnueabihf/libm.so
:: /build/gnome-46-2404-sdk/stage/usr/lib/arm-linux-gnueabihf/libc.a
:: /build/gnome-46-2404-sdk/stage/usr/lib/arm-linux-gnueabihf/libm.a
:: /build/gnome-46-2404-sdk/stage/usr/lib/arm-linux-gnueabihf/libc.so
[--snip--]

Note the lack of libc.so.6, and upon further inspection libc.so is just a "GNU ld symlink" to the former.

snapcraft-libtool-amd64-6736356 ../stage/usr/lib/x86_64-linux-gnu# cat /root/stage/usr/lib/x86_64-linux-gnu/libc.so
/* GNU ld script
   Use the shared library, but some functions are only in
   the static library, so try that secondarily.  */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a  AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )

Libtool only pulled libc6-dev and not libc6 which includes libc.so.6. So the static linking came as a fallback.

As obvious from the failed logs, statically linking also fails. Both libm.a and libc.a are present and are (or point to) valid AR though.

So next question is: What exactly is in there, in different architectures? I did

pull-lp-debs -a riscv64 libc6-dev noble

and then the same for x64 (where the build succeeds) for comparison sake and then ran a Nm on them:

Risc-V:

~/canonical/packages/libc-risvc-noble/libc6-dev/usr/lib/riscv64-linux-gnu% for lib in libm libc; do
  echo ">>$lib<<"
  2>/dev/null nm $lib.a | grep  -e '__frexpf$' -e '__ldexpf$' -e '__frexp$' -e '__ldexp$'
done
>>libm<<
                 U __frexp
                 U __frexp
                 U __ldexp
                 U __frexpf
                 U __frexpf
                 U __ldexpf
>>libc<<
0000000000000000 T __frexp
0000000000000000 T __ldexp
0000000000000000 T __frexpf
0000000000000000 T __ldexpf

Amd64:

~/canonical/packages/libc-amd-noble/libc6-dev/usr/lib/x86_64-linux-gnu% for lib in libm libc; do
  echo ">>$lib<<"
  2>/dev/null nm $lib.a | grep  -e '__frexpf$' -e '__ldexpf$' -e '__frexp$' -e '__ldexp$'
done
>>libm<<
>>libc<<
0000000000000000 T __frexp
0000000000000000 T __ldexp
0000000000000000 T __frexpf
0000000000000000 T __ldexpf

So in both cases the symbols are defined in libc but in Risc-V they are undefined in libm.*

One earlier attempt I made was to have GTK's Meson use -lc too, but the build failed likewise. Note the parameter order though: -lc -lm. I guess the libm undefinedness "takes over" the libc definedness in that call, but as is clear I'm no expert in Ld.

I went back to the Risc-V virtual machine to quickly check that (instead of submitting a new build):

ubuntu@ubuntu:~$ gcc a.c /usr/lib/riscv64-linux-gnu/lib{c,m}.a
/usr/bin/ld: /usr/lib/riscv64-linux-gnu/libm.a(s_cbrtf.o): in function `__cbrtf':
(.text+0x2e): undefined reference to `__frexpf'

collect2: error: ld returned 1 exit status
ubuntu@ubuntu:~$ gcc a.c /usr/lib/riscv64-linux-gnu/lib{m,c}.a

So first m and then c does link! However, maybe I screwed that up anyway? As the executable segfaults.

ubuntu@ubuntu:~$ ./a.out
Segmentation fault (core dumped)

(Is that what I get for following Stackoverflow blindly?)

I found that with -static works with either order:

ubuntu@ubuntu:~$ gcc a.c -static -lm -lc
ubuntu@ubuntu:~$ ./a.out
2.000000 = 8.000000 ^ (1 / 3)
16.000000 =  ^ (1 / 3)
ubuntu@ubuntu:~$ gcc a.c -static -lc -lm
ubuntu@ubuntu:~$ ./a.out
2.000000 = 8.000000 ^ (1 / 3)
16.000000 =  ^ (1 / 3)

So I guess that that build with -lc failed because Meson prepares the cc call to dynamically link (so without -static) and the fallback to static is done by the linker itself but without -static that would either fail to link as it did, or worse, segfault at run-time.

Anyways... I don't think we absolutely need to go further. I'm still curious about the reason and mechanism that allows gcc to link and then segfault, though.

*The output is different in Plucky and makes me believe the issue wouldn't be present there. Of course I went that way initially, adding more confusion!

nteodosio avatar Apr 24 '25 10:04 nteodosio

This made a come-back.

libm.so -> libm.so.6, which does not exist.

This caused Firefox' builds to eventually fail in Riscv and Aarch32.

nteodosio avatar Aug 05 '25 12:08 nteodosio