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

.NET SDK uses wrong libc name on musl libc #83779

Open
xgqt opened this issue Mar 22, 2023 · 32 comments
Open

.NET SDK uses wrong libc name on musl libc #83779

xgqt opened this issue Mar 22, 2023 · 32 comments
Labels
area-Host question Answer questions and provide assistance, not an issue with source code or documentation. source-build Issues relating to dotnet/source-build
Milestone

Comments

@xgqt
Copy link

xgqt commented Mar 22, 2023

Describe the bug

On a Gentoo system built with musl libc the library libc.musl-x86_64.so.1 is inaccessible.

Expectations

.NET SDK links to a more widely known musl library name.

Further technical details

musl version is: 1.2.3-r7

See also https://bugs.gentoo.org/894760

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Mar 22, 2023
@xgqt
Copy link
Author

xgqt commented Mar 22, 2023

This also propagates to programs built with such dotnet exe.

See: https://bugs.gentoo.org/894758

@xgqt
Copy link
Author

xgqt commented Mar 22, 2023

It is possible to build applications with this seemingly broken dotnet since it ALSO links to a libc library: libc.so.6 => /lib64/libc.so.6 (0x00007f16a4d49000).

The .NET SDK musl version was probably supposed to be used on a glibc Linux system but for a musl packaging?
Is this correct? How should the musl version be used on Linux systems without glibc?

@am11
Copy link
Member

am11 commented Mar 22, 2023

.NET SDK links to a more widely known musl library name.

We don't explicitly specify the libc name or path, we are using the system defaults (Alpine Linux):

# use gcc to compile a hello world app
$ echo "int main(){}" | gcc -xc -
# inspect the executable
$ ldd ./a.out 
     /lib/ld-musl-x86_64.so.1 (0x7f15b41a7000)
     libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f15b41a7000)
$ readelf -a ./a.out | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libc.musl-x86_64.so.1]

# compare with dotnet executable

$ ldd $(command -v dotnet)
        /lib/ld-musl-x86_64.so.1 (0x7f088e769000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f088e507000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f088e4e9000)
        libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f088e769000)
$ readelf -a $(command -v dotnet) | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.musl-x86_64.so.1]

Do you have a suggestion to improve DT_NEEDED at build time? If you built everything on gentoo-musl (.NET Runtime + SDK) then it should use whatever defaults were there on the build machine.

Alternatively, you can create a libc.musl-x86_64.so.1 -> /usr/lib/libc.so symlink on your system if it is missing it.

Another alternative is to patch the ELF after the fact:

# Prerequisite: emerge equivalent of 'apk add patchelf'

$ patchelf --replace-needed libc.musl-x86_64.so.1 libc.so $(command -v dotnet)
# or patch all ELF files under install dir
$ find /usr/share/dotnet/ -exec file {} \; | grep ELF | \
     while IFS=: read name rest; do patchelf --replace-needed libc.musl-x86_64.so.1 libc.so $name; done
# (and ~/.nuget dir if needed)

# verify desired results
$ ldd $(command -v dotnet)
        /lib/ld-musl-x86_64.so.1 (0x7f2186a5d000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7f21867f9000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7f21867db000)
        libc.so => /lib/ld-musl-x86_64.so.1 (0x7f2186a5d000)
$ readelf -a $(command -v dotnet) | grep NEEDED
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]

@xgqt
Copy link
Author

xgqt commented Mar 22, 2023

@am11 thank you for your quick response.
Unfortunately you will have to take my words with a grain of salt because I am not a toolchain expert.

Do you have a suggestion to improve DT_NEEDED at build time? If you built everything on gentoo-musl (.NET Runtime + SDK) then it should use whatever defaults were there on the build machine.

Currently we struggle with building .NET SDK from source under Portage mainly because the network restriction and huge build size, see: gentoo/gentoo#21112

So we are talking about binary distributed by Microsoft / .NET project now only.

Alternatively, you can create a libc.musl-x86_64.so.1 -> /usr/lib/libc.so symlink on your system if it is missing it.

I hope a person form Gentoo Toolchain Project or one of musl maintainers in Gentoo could comment on that.

Another alternative is to patch the ELF after the fact:

I think this is what we will have to do.
Thanks for the snippet :D

@xgqt
Copy link
Author

xgqt commented Mar 22, 2023

Im worried that subsequent application builds will also want to link to "wrong" musl libc name.
Do you know if this is taken from some place defined by .NET SDK?
Im taking about this issue: https://bugs.gentoo.org/894758

@danmoseley
Copy link
Member

Cc @richlander

@danmoseley danmoseley transferred this issue from dotnet/sdk Mar 22, 2023
@ghost
Copy link

ghost commented Mar 22, 2023

Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov
See info in area-owners.md if you want to be subscribed.

Issue Details

Describe the bug

On a Gentoo system built with musl libc the library libc.musl-x86_64.so.1 is inaccessible.

Expectations

.NET SDK links to a more widely known musl library name.

Further technical details

musl version is: 1.2.3-r7

See also https://bugs.gentoo.org/894760

Author: xgqt
Assignees: -
Labels:

area-Host, untriaged

Milestone: -

@am11
Copy link
Member

am11 commented Mar 22, 2023

@xgqt, I am not sure if that issue was just a lint warning or the app actually failed to run? In another issue (https://bugs.gentoo.org/894760#c3), I see this link:

        /lib/ld-musl-x86_64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f16a5287000)

which suggests that the link was resolved on gentoo. Try running that app.

@xgqt
Copy link
Author

xgqt commented Mar 22, 2023

@xgqt, I am not sure if that issue was just a lint warning or the app actually failed to run? In another issue (https://bugs.gentoo.org/894760#c3), I see this link:

        /lib/ld-musl-x86_64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f16a5287000)

which suggests that the link was resolved on gentoo. Try running that app.

It must run since it can compile .NET applications,
in https://bugs.gentoo.org/894758 it compiles csharp-language-server.

@xgqt
Copy link
Author

xgqt commented Mar 22, 2023

@xgqt, I am not sure if that issue was just a lint warning or the app actually failed to run? In another issue (https://bugs.gentoo.org/894760#c3), I see this link:

        /lib/ld-musl-x86_64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f16a5287000)

which suggests that the link was resolved on gentoo. Try running that app.

It must run since it can compile .NET applications, in https://bugs.gentoo.org/894758 it compiles csharp-language-server.

This is the logfile: https://894758.bugs.gentoo.org/attachment.cgi?id=851776

And quoting the build process:

>>> Unpacking source...
>>> Unpacking csharp-language-server-0.5.7.tar.gz to /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work
>>> Unpacking csharp-language-server-0.5.7-prebuilt.tar.xz to /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work
>>> Source unpacked in /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work
>>> Preparing source in /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7 ...
>>> Source prepared.
>>> Configuring source in /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7 ...
 * Running dotnet restore /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src --source /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/nuget_packages -p:TargetFramework=net6.0 ...
=  Determining projects to restore...
=========  Restored /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src/CSharpLanguageServer.Tests/CSharpLanguageServer.Tests.fsproj (in 475 ms).
  Restored /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src/CSharpLanguageServer/CSharpLanguageServer.fsproj (in 474 ms).
 [ ok ]
>>> Source configured.
>>> Compiling source in /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7 ...
 * Running dotnet build --configuration Debug --no-restore --no-self-contained --nologo --output /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7_net6.0_Debug/csharp-language-server -maxCpuCount:1 -p:TargetFramework=net6.0 /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src ...
==  CSharpLanguageServer -> /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7_net6.0_Debug/csharp-language-server/CSharpLanguageServer.dll
  CSharpLanguageServer -> /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7_net6.0_Debug/csharp-language-server/CSharpLanguageServer.dll
/var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src/CSharpLanguageServer.Tests/DocumentationTests.fs(102,1): warning FS0988: Main module of program is empty: nothing will happen when it is run [/var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src/CSharpLanguageServer.Tests/CSharpLanguageServer.Tests.fsproj]
=  CSharpLanguageServer.Tests -> /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7_net6.0_Debug/csharp-language-server/CSharpLanguageServer.Tests.dll

Build succeeded.

/var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src/CSharpLanguageServer.Tests/DocumentationTests.fs(102,1): warning FS0988: Main module of program is empty: nothing will happen when it is run [/var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/work/csharp-language-server-0.5.7/src/CSharpLanguageServer.Tests/CSharpLanguageServer.Tests.fsproj]
    1 Warning(s)
    0 Error(s)

Time Elapsed 00:00:07.48
 [ ok ]
>>> Source compiled.
>>> Test phase [not enabled]: dev-dotnet/csharp-language-server-0.5.7

>>> Install dev-dotnet/csharp-language-server-0.5.7 into /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/image
>>> Completed installing dev-dotnet/csharp-language-server-0.5.7 into /var/tmp/portage/dev-dotnet/csharp-language-server-0.5.7/image

 * Final size of build directory: 1084284 KiB ( 1.0 GiB)
 * Final size of installed tree:    57832 KiB (56.4 MiB)

 * QA Notice: Unresolved soname dependencies:
 * 
 * 	/usr/share/csharp-language-server/CSharpLanguageServer: libc.musl-x86_64.so.1
 * 
strip: x86_64-gentoo-linux-musl-strip --strip-unneeded -N __gentoo_check_ldflags__ -R .comment -R .GCC.command.line -R .note.gnu.gold-version
   /usr/share/csharp-language-server/CSharpLanguageServer
>>> Done.

@am11
Copy link
Member

am11 commented Mar 22, 2023

Yup, I was referring to that QA Notice, if the app runs, that means dynamic linker is happy. You can ignore the lint / QA warning.

@xgqt
Copy link
Author

xgqt commented Mar 22, 2023

Yup, I was referring to that QA Notice, if the app runs, that means dynamic linker is happy. You can ignore the lint / QA warning.

Well, not really, "we" can not ignore it,
in Gentoo we care very much to have no QA warnings, mislinked or missing libraries.

But yes, this is not a critical issue in term of that the app can run.

BUT it might be producing "garbage" applications --> #83779 (comment)

@am11
Copy link
Member

am11 commented Mar 22, 2023

BUT it might be producing "garbage" applications

Not sure I followed. If the app is running that means dynamic loader successfully loaded the libc among other dependencies at the startup. Otherwise you will get SIGABRT right away when you execute the app. libc is the first library dynamic linker loads at runtime (discounting the ELF interpreter). If you are not getting any error when running the app, then this is a bogus warning. QA tool should be fixed.

@rmboggs
Copy link

rmboggs commented Apr 28, 2023

Hi,

We are running into a similar issue on void running musl as well with a missing libc.musl-x86_64.so.1 link. Is there any way to switch that dependency to something more generic, like libc.so instead?

@am11
Copy link
Member

am11 commented Apr 28, 2023

@rmboggs, hello. I tested .NET 8 build in void-linux docker container, it seems to be running just fine.

Full story:

# interactively run the container:
#   https://github.com/void-linux/void-docker/pkgs/container/void-linux/68157668?tag=20230204RC01-thin-bb-x86_64-musl
$ docker run -it ghcr.io/void-linux/void-linux:20230204RC01-thin-bb-x86_64-musl

# inside the container

# 1. install dependencies (for SDK commands)
$ xbps-install -Sy curl openssl icu-libs

# 2. download and install .NET
$ mkdir ~/.dotnet && \
    curl -sSL https://aka.ms/dotnet/8.0.1xx/daily/dotnet-sdk-linux-musl-x64.tar.gz | tar xzf - -C ~/.dotnet && \
    export PATH=$PATH:~/.dotnet

# 3. create a simple web api app and run it
$ dotnet new api -n api1 && cd api1
# add .NET 8 preview feed
$ cat > nuget.config <<EOF
<configuration>
  <packageSources>
    <add key="dotnet8" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json" />
  </packageSources>
</configuration>
EOF
$ dotnet run

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /api1

# 4. try AOT: first the prereqs
$ xbps-install -Sy clang zlib-devel
# 5. publish AOT app
$ dotnet publish -o dist -c Release -p:PublishAot=true
$ dist/api1

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /api1

@rmboggs
Copy link

rmboggs commented Apr 28, 2023

Hi @am11,
I am actually working on packaging dotnet 7 for a void package on x64-musl. It builds fine but fails during the package step for SDK because it can't find the package containing libc.musl-x86_64.so.1 because the musl package for void doesn't contain that sym link. I'm hoping that, because the file in question is just a link anyway, that this can be updated to point to the libc.so file instead. Does this make sense?

@am11
Copy link
Member

am11 commented Apr 28, 2023

Can you share the output of ldd $(command -v dotnet)?

@rmboggs
Copy link

rmboggs commented Apr 29, 2023

Hi @am11,
I just did the command you asked and it comes up as follows for dotnet:

	/lib/ld-musl-x86_64.so.1 (0x7f8e0be1c000)
	/usr/lib/libswmhack.so.0.0 => /usr/lib/libswmhack.so.0.0 (0x7f8e0be03000)
	libstdc++.so.6 => /lib/libstdc++.so.6 (0x7f8e0ba00000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x7f8e0bde5000)
	libc.so => /lib/ld-musl-x86_64.so.1 (0x7f8e0be1c000)
	libX11.so.6 => /lib/libX11.so.6 (0x7f8e0b8be000)
	libxcb.so.1 => /lib/libxcb.so.1 (0x7f8e0bdbc000)
	libXau.so.6 => /lib/libXau.so.6 (0x7f8e0bdb7000)
	libXdmcp.so.6 => /lib/libXdmcp.so.6 (0x7f8e0bdaf000)

The file in question isn't there. However, I dug further and found the vstest.console file in the sdk files has this output for ldd:

	/lib/ld-musl-x86_64.so.1 (0x7f2fd7af2000)
	/usr/lib/libswmhack.so.0.0 => /usr/lib/libswmhack.so.0.0 (0x7f2fd7ad7000)
	libstdc++.so.6 => /lib/libstdc++.so.6 (0x7f2fd7600000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x7f2fd7ab9000)
	libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f2fd7af2000) <-- Here is the reference
	libX11.so.6 => /lib/libX11.so.6 (0x7f2fd7977000)
	libxcb.so.1 => /lib/libxcb.so.1 (0x7f2fd794e000)
	libXau.so.6 => /lib/libXau.so.6 (0x7f2fd7949000)
	libXdmcp.so.6 => /lib/libXdmcp.so.6 (0x7f2fd7941000)

I'm not sure how/why vstest.console is linking to that file when it isn't on my system. Especially when it looks like it is trying to link to the ld-musl-x86_64.so.1 above.

Anything I can do to avoid the reference to the missing file for vstest.console?

@am11
Copy link
Member

am11 commented Apr 29, 2023

	libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f2fd7af2000) <-- Here is the reference

and

	libc.so => /lib/ld-musl-x86_64.so.1 (0x7f8e0be1c000)

are resolving to the same "ELF intepreter". Which means if dotnet or vstest.console are not terminating with SIGABRT etc. it shouldn't matter which name was encoded in DT_NEEDED header, as long as dynamic loader can make sense of it. Dynamic loader is smart and looks beyond the verbatim names on the filename.

So the real question is, is the binary actually failing or some QA/linting took is complaining about the name? If it is former, then please explain a bit, when/how it fails, what's the exit code when it fails (echo $?) etc. If it is latter, then let me show you how to patch the DT_NEEDED header to get by the bogus lint warnings:

(replace aarch64 with x86_64)

# first check the header
$ readelf -d that_binary
Dynamic section at offset 0x92f930 contains 34 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/netcoredeps]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.musl-aarch64.so.1]
                                                              ^^^
                                             it will look something like this
....

# patch it (e.g. `apk add patchelf`)
$ patchelf --replace-needed libc.musl-aarch64.so.1 libc.so that_binary

# check the headers again
$ readelf -d that_binary
Dynamic section at offset 0x92f930 contains 34 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/netcoredeps]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
                                                              ^^^
                                       it "looks" good but binary runs the same 😅
....

@rmboggs
Copy link

rmboggs commented Apr 30, 2023

	libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f2fd7af2000) <-- Here is the reference

and

	libc.so => /lib/ld-musl-x86_64.so.1 (0x7f8e0be1c000)

are resolving to the same "ELF intepreter". Which means if dotnet or vstest.console are not terminating with SIGABRT etc. it shouldn't matter which name was encoded in DT_NEEDED header, as long as dynamic loader can make sense of it. Dynamic loader is smart and looks beyond the verbatim names on the filename.

So the real question is, is the binary actually failing or some QA/linting took is complaining about the name? If it is former, then please explain a bit, when/how it fails, what's the exit code when it fails (echo $?) etc. If it is latter, then let me show you how to patch the DT_NEEDED header to get by the bogus lint warnings:

It's actually failing for the latter, during the install/package stage of the package process.

(replace aarch64 with x86_64)

# first check the header
$ readelf -d that_binary
Dynamic section at offset 0x92f930 contains 34 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/netcoredeps]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.musl-aarch64.so.1]
                                                              ^^^
                                             it will look something like this
....

# patch it (e.g. `apk add patchelf`)
$ patchelf --replace-needed libc.musl-aarch64.so.1 libc.so that_binary

# check the headers again
$ readelf -d that_binary
Dynamic section at offset 0x92f930 contains 34 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/netcoredeps]
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             Shared library: [libstdc++.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so]
                                                              ^^^
                                       it "looks" good but binary runs the same 😅
....

Thanks, tried this a bit yesterday without success. So there is either another binary in the sdk somewhere that i need to search for or the process that is failing is using something different to check. I'll see if I can keep digging into this.

@agocke agocke added this to AppModel Jul 10, 2023
@agocke agocke added the source-build Issues relating to dotnet/source-build label Jul 19, 2023
@agocke agocke added this to the Future milestone Jul 19, 2023
@agocke agocke added question Answer questions and provide assistance, not an issue with source code or documentation. and removed untriaged New issue has not been triaged by the area owner labels Jul 19, 2023
@xgqt
Copy link
Author

xgqt commented Jan 20, 2024

Currently this bothers us quite a bit in Gentoo, see https://bugs.gentoo.org/894760 and "Blocks:" tag.

Short term solution is to patchelf all .NET-produced binaries conditionally for musl installations.

@danmoseley
Copy link
Member

@agocke Just curious, why do we not link to the more generic name?

@am11
Copy link
Member

am11 commented Jan 20, 2024

@xgqt, what does this report on gentoo:

$ curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --quality daily --channel 9.0 --install-dir ~/.dotnet9
$ ldd ~/.dotnet9/dotnet
$ ~/.dotnet9/dotnet --info # does this fail? it works on alpine and void-linux (musl edition)

As said, we do not explicitly link against any specific ABI version, we pick a minimal OS and link against its libc. Meaning if your libc is older or built differently (e.g. with a different or without the SONAME), then it may not be easy for static analyzer / linter etc. to distinguish that the mismatches it has found are not the real issues; the real dynamic loader will resolve this:
libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1

@xgqt
Copy link
Author

xgqt commented Jan 20, 2024

@xgqt, what does this report on gentoo:

$ curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --quality daily --channel 9.0 --install-dir ~/.dotnet9
$ ldd ~/.dotnet9/dotnet
$ ~/.dotnet9/dotnet --info # does this fail? it works on alpine and void-linux (musl edition)

As said, we do not explicitly link against any specific ABI version, we pick a minimal OS and link against its libc. Meaning if your libc is older or built differently (e.g. with a different or without the SONAME), then it may not be easy for static analyzer / linter etc. to distinguish that the mismatches it has found are not the real issues; the real dynamic loader will resolve this: libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1

@am11

Info returns:

.NET SDK:
 Version:           9.0.100-alpha.1.24070.2
 Commit:            cac6c93287
 Workload version:  9.0.100-manifests.0d37fe7a

Runtime Environment:
 OS Name:     gentoo
 OS Version:  2.14
 OS Platform: Linux
 RID:         linux-musl-x64
 Base Path:   /root/.dotnet9/sdk/9.0.100-alpha.1.24070.2/

.NET workloads installed:
There are no installed workloads to display.

Host:
  Version:      9.0.0-alpha.1.24066.33
  Architecture: x64
  Commit:       dbb335c6ba

.NET SDKs installed:
  9.0.100-alpha.1.24070.2 [/root/.dotnet9/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 9.0.0-alpha.1.24068.16 [/root/.dotnet9/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 9.0.0-alpha.1.24066.33 [/root/.dotnet9/shared/Microsoft.NETCore.App]

Other architectures found:
  None

Environment variables:
  Not set

global.json file:
  Not found

Learn more:
  https://aka.ms/dotnet/info

Download .NET:
  https://aka.ms/dotnet/download

ldd show:

 /lib/ld-musl-x86_64.so.1 (0x7f7264a80000)
        libstdc++.so.6 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libstdc++.so.6 (0x7f7264816000)
        libgcc_s.so.1 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libgcc_s.so.1 (0x7f72647f3000)
        libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f7264a80000)

... looks like no failure? ...

but lddtree shows:

dotnet => /root/.dotnet9/dotnet (interpreter => /lib/ld-musl-x86_64.so.1)
    libstdc++.so.6 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libstdc++.so.6
        libc.so => /usr/lib/libc.so
    libgcc_s.so.1 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libgcc_s.so.1
    libc.musl-x86_64.so.1 => not found

... and it can not find libc.musl-x86_64.so.1

So I think that ldd should not be taken as a source of truth here.

@xgqt
Copy link
Author

xgqt commented Jan 20, 2024

This is what ldd on libcoreclr.so returns

foxylady ~ # ldd ~/.dotnet9/shared/Microsoft.NETCore.App/9.0.0-alpha.1.24066.33/libcoreclr.so
        ldd (0x7f589ffbe000)
        libgcc_s.so.1 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libgcc_s.so.1 (0x7f589f8a9000)
        libstdc++.so.6 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libstdc++.so.6 (0x7f589f653000)
        libc.musl-x86_64.so.1 => ldd (0x7f589ffbe000)
foxylady ~ # lddtree ~/.dotnet9/shared/Microsoft.NETCore.App/9.0.0-alpha.1.24066.33/libcoreclr.so
libcoreclr.so => /root/.dotnet9/shared/Microsoft.NETCore.App/9.0.0-alpha.1.24066.33/libcoreclr.so (interpreter => none)
    libgcc_s.so.1 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libgcc_s.so.1
        libc.so => /usr/lib/libc.so
    libstdc++.so.6 => /usr/lib/gcc/x86_64-gentoo-linux-musl/13/libstdc++.so.6
    libc.musl-x86_64.so.1 => not found
foxylady ~ #

@am11
Copy link
Member

am11 commented Jan 20, 2024

Thanks. So the binary is working flawlessly. Based on this info, you can open a bug with QA tool upstream which is raising false-negatives; assuming the QA tool is supposed to validate "whether or not the OS ld will be able to load the binary and its linked dependencies" (which is what ldd utility reports).

@xgqt
Copy link
Author

xgqt commented Jan 21, 2024

@agocke Just curious, why do we not link to the more generic name?

What do you think @am11 of what @agocke suggested?

@xgqt
Copy link
Author

xgqt commented Jan 22, 2024

Could any .NET developer point to code that is used to determine what libc is linked when dotnet build/publish is used for producing executables?

@MichalPetryka
Copy link
Contributor

Could any .NET developer point to code that is used to determine what libc is linked when dotnet build/publish is used for producing executables?

Pretty sure that the executable is build with the native runtime and only patched later with the logo and such.

@xgqt
Copy link
Author

xgqt commented Jan 22, 2024

Could any .NET developer point to code that is used to determine what libc is linked when dotnet build/publish is used for producing executables?

Pretty sure that the executable is build with the native runtime and only patched later with the logo and such.

Hmm if so by patching runtime linkage "errors" we should get "correct" exes (for Gentoo).

@am11
Copy link
Member

am11 commented Jan 22, 2024

If there was any linkage error, none of the executables would run. If executables are running, ignore the naive QA tool.

@xgqt
Copy link
Author

xgqt commented Jan 23, 2024

Could any .NET developer point to code that is used to determine what libc is linked when dotnet build/publish is used for producing executables?

Pretty sure that the executable is build with the native runtime and only patched later with the logo and such.

Hmm if so by patching runtime linkage "errors" we should get "correct" exes (for Gentoo).

@MichalPetryka

I tried to investigate my assumption and hack around with patchelf

sos=(
    /opt/dotnet-sdk-bin-8.0/dotnet
    /opt/dotnet-sdk-bin-8.0/host/fxr/8.0.1/libhostfxr.so
    /opt/dotnet-sdk-bin-8.0/packs/Microsoft.NETCore.App.Host.linux-musl-x64/8.0.1/runtimes/linux-musl-x64/native/apphost
    /opt/dotnet-sdk-bin-8.0/packs/Microsoft.NETCore.App.Host.linux-musl-x64/8.0.1/runtimes/linux-musl-x64/native/libnethost.so
    /opt/dotnet-sdk-bin-8.0/packs/Microsoft.NETCore.App.Host.linux-musl-x64/8.0.1/runtimes/linux-musl-x64/native/singlefilehost
    /opt/dotnet-sdk-bin-8.0/sdk/8.0.101/AppHostTemplate/apphost
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/createdump
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libSystem.Globalization.Native.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libSystem.IO.Compression.Native.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libSystem.Native.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libSystem.Net.Security.Native.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libSystem.Security.Cryptography.Native.OpenSsl.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libclrgc.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libclrjit.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libcoreclr.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libcoreclrtraceptprovider.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libhostpolicy.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libmscordaccore.so
    /opt/dotnet-sdk-bin-8.0/shared/Microsoft.NETCore.App/8.0.1/libmscordbi.so
)

for so in ${sos[@]} ; do
    patchelf --remove-needed libc.musl-x86_64.so.1 $so
    patchelf --add-needed libc.so $so
done

But with no success, building a example software - Coco in this case produced a binary still requiring the missing library:

image

So probably the runtime libraries (if any) to build Coco come from core NuGet packages.
Which means one would have to patch the following NuGets:

  • microsoft.aspnetcore.app.runtime.linux-musl-x64.8.0.1.nupkg
  • microsoft.netcore.app.runtime.linux-musl-x64.8.0.1.nupkg
  • microsoft.aspnetcore.app.ref.8.0.1.nupkg
  • microsoft.netcore.app.ref.8.0.1.nupkg
  • microsoft.netcore.app.host.linux-musl-x64.8.0.1.nupkg (most likely the offender)

This also means if we compile .NET SDK on Gentoo with musl libc and the resulting package will not have no despondencies on libc.musl-x86_64.so.1 the software produced by it will gain them! Because a probuilt microsoft.netcore.app.host.linux-musl-x64.8.0.1.nupkg is used.

Either that or .NET SDK hardcodes libc.musl-x86_64.so.1 dependency. I have no other ides for now.

gentoo-bot pushed a commit to gentoo/gentoo that referenced this issue Jan 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-Host question Answer questions and provide assistance, not an issue with source code or documentation. source-build Issues relating to dotnet/source-build
Projects
Status: No status
Development

No branches or pull requests

6 participants