conda-forge / linux-sysroot-feedstock

A conda-smithy repository for linux-sysroot.
BSD 3-Clause "New" or "Revised" License
3 stars 15 forks source link

dlsym() returns illegal implementation of sin() with recent glibc #45

Closed teobouvard closed 1 year ago

teobouvard commented 1 year ago

Solution to issue cannot be found in the documentation.

Issue

Hello,

When dynamically loading the sin() function from the libm.so.6 provided by this package, I get an FMA4 implementation (__sin_fma4), which is not supported by my CPU (AMD Ryzen 7 3700X). Running the resulting binary triggers an illegal instruction (vfmaddsd).

You should be able to reproduce this issue by compiling the following program

#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char** argv) {
    void *handle;
    double (*sin_func)(double);
    char *error;

    handle = dlopen(argv[1], RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "Error: %s\n", dlerror());
        return 1;
    }

    dlerror(); /* Clear any existing error */
    sin_func = dlsym(handle, "sin");
    error = dlerror();
    if (error != NULL) {
        fprintf(stderr, "Error: %s\n", error);
        dlclose(handle);
        return 1;
    }

    printf("sin(1) = %f\n", (*sin_func)(1.0));
    dlclose(handle);
    return 0;
}

using

gcc -g illegal.c

and then execute it, giving it the path to the libm shared library bundled with this conda package.

$ ./a.out ~/.conda/envs/libm_issue/x86_64-conda-linux-gnu/sysroot/lib64/libm.so.6
[1]    168581 illegal hardware instruction (core dumped)  ./a.out

On my host, this results in an illegal instruction. Running it through gdb shows that the cause is the FMA4 instruction vfmaddsd.

Program received signal SIGILL, Illegal instruction.
0x00007ffff7a500e2 in __sin_fma4 () from /home/user/.conda/envs/libm_issue/x86_64-conda-linux-gnu/sysroot/lib64/libm.so.6

A few informations:

$ uname -a
Linux HoG 6.1.12-arch1-1 #1 SMP PREEMPT_DYNAMIC Tue, 14 Feb 2023 22:08:08 +0000 x86_64 GNU/Linux

$ gcc --version
gcc (GCC) 12.2.1 20230201

$ ld --version
GNU ld (GNU Binutils) 2.40

$ /lib64/libc.so.6
GNU C Library (GNU libc) stable release version 2.37.
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 12.2.1 20230201.
libc ABIs: UNIQUE IFUNC ABSOLUTE
Minimum supported kernel: 4.4.0

$ cat /proc/cpuinfo | head -n 28
processor   : 0
vendor_id   : AuthenticAMD
cpu family  : 23
model       : 113
model name  : AMD Ryzen 7 3700X 8-Core Processor
stepping    : 0
microcode   : 0x8701013
cpu MHz     : 3876.885
cache size  : 512 KB
physical id : 0
siblings    : 16
core id     : 0
cpu cores   : 8
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 16
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf rapl pni pclmulqdq monitor ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw ibs skinit wdt tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb cat_l3 cdp_l3 hw_pstate ssbd mba ibpb stibp vmmcall fsgsbase bmi1 avx2 smep bmi2 cqm rdt_a rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local clzero irperf xsaveerptr rdpru wbnoinvd arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload vgif v_spec_ctrl umip rdpid overflow_recov succor smca sev sev_es
bugs        : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass retbleed smt_rsb
bogomips    : 7189.97
TLB size    : 3072 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 43 bits physical, 48 bits virtual
power management: ts ttp tm hwpstate cpb eff_freq_ro [13] [14]

Note that this procedure works on CentOS7, using the same version of libm (2.17) but a matching version of the glibc's linker/loader. This also works on my host when using the system's libm.so, which is more recent (2.37).

I tried building version 2.17 of libm from glibc sources, but when running my test case against the built shared library, it failed at the dlopen() call:

$ ./a.out ../glibc/build/math/libm.so
dlopen: ../glibc/build/math/libm.so: undefined symbol: __get_cpu_features, version GLIBC_PRIVATE

Thanks for your answers.

Installed packages

# Name                               Version  Build 
_sysroot_linux-64_curr_repodata_hack 3        haa98f57_10  
kernel-headers_linux-64              3.10.0   h57e8cba_10  
sysroot_linux-64                     2.17     h57e8cba_10

Environment info

active environment : test_libm
    active env location : /home/user/.conda/envs/test_libm
            shell level : 1
       user config file : /home/user/.condarc
 populated config files : /etc/conda/condarc
          conda version : 22.11.1
    conda-build version : 3.23.1
         python version : 3.9.12.final.0
       virtual packages : __archspec=1=x86_64
                          __cuda=12.0=0
                          __glibc=2.37=0
                          __linux=6.2.2=0
                          __unix=0=0
       base environment : /opt/miniconda3  (read only)
      conda av data dir : /opt/miniconda3/etc/conda
  conda av metadata url : None
           channel URLs : https://repo.anaconda.com/pkgs/main/linux-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/r/linux-64
                          https://repo.anaconda.com/pkgs/r/noarch
          package cache : /home/user/.conda/pkgs
       envs directories : /home/user/.conda/envs
                          /opt/miniconda3/envs
               platform : linux-64
             user-agent : conda/22.11.1 requests/2.27.1 CPython/3.9.12 Linux/6.2.2-arch1-1 arch/rolling glibc/2.37
                UID:GID : 1000:1000
             netrc file : None
           offline mode : False
isuruf commented 1 year ago

libm.so provided by this package is supposed to be used for building packages only. Using the package by preloading it or dlopening it is unsupported.

teobouvard commented 1 year ago

Oh ok, thanks for the answer!

Do you know why I'm still able to dlopen it, but it resolves an unsupported implementation for the sin symbol ? Just curious.