Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Mon, 17 Apr 2023 04:36:24 +0200
From: Lorenz Hipp <jHhvLtwZki@...isch.de>
To: musl@...ts.openwall.com
Subject: Add musl-ldd for user convenience and to avoid naming conflict

Greetings everyone!

(As my first post to this mailing list, I hope I did everything right
regarding the technical stuff, like formatting. Otherwise, please
tell me.)


This is a suggestion to fix a minor, but (at least for me) somewhat
annoying issue.

The user (or some CI/AT software) sometimes wants to inspect just built
programs by running

    ldd program

to see or record the actual linked libraries and their (hopefully correct)
paths.


The default "ldd" program on most Linux systems is surely the script
provided by the gnu libc implementation.

Unfortunately, (for reasons I won't go into detail) their program
cannot work properly with programs linked with musl, as it prints an
error message :

    musl-gcc -o Test-musl Test-musl.c
    ldd Test-musl

    ./Test-musl: error while loading shared libraries: /usr/lib/libc.so: invalid ELF header

Since the mentioned file is of course a linker script and just text, it
cannot have a valid ELF header.


Following the FAQ on the musl website at

    https://wiki.musl-libc.org/faq.html#Q:-Where-is-%3Ccode%3Eldd%3C/code%3E?

the musl linker actually has 'ldd' functionality, which is used when
it is called as "ldd".

Quote :

    Just create a symlink from ld-musl-$ARCH.so to /bin/ldd.

At least on machines where software is developed, it would not be
a good idea to replace the glibc ldd script with a link to the musl
linker, because of .. reasons (such as slightly different output behaviour).


I don't know, where other people or companies, who work with musl,
install musl (mine is installed similar to what Arch [1] does) and how they
work around this (if at all), but even if musl (or at least its two
programs/wrapper scripts) are installed in

    /usr/local
or
    $HOME/musl

, you then have two "ldd" programs, have to adjust your PATH environment
variable and need to remember that "ldd" and "/usr/bin/ldd" are two
different programs. And this is what can get annoying, especially if new
co-workers are involved.

If, for some reason, someone or something doesn't know about it and assumes
"ldd" is the glibc variant, you end up possibly with issues; not funny,
when there is some kind of (closed source) continuous integration (CI)
or automated testing (AT) software/process involved.


Since a developer who works with musl will most likely end up to use

    musl-clang
    musl-gcc

anyway, I propose that a third program, or rather a symbolic link is
installed:

    musl-ldd

I expect that the user (or any CI/AT software) doesn't have a problem
with a third program, especially for the profit to avoid a (naming)
conflict with glibc ldd.


So, how to solve this?
There are two simple approaches I managed to identify.


1.  This one involves to change some source code in

    https://git.musl-libc.org/cgit/musl/tree/ldso/dynlink.c

to make the linker ready to change to 'ldd' mode not only when it's
called as (exactly) 'ldd', but also as 'musl-ldd'.

Required patch would be :

--- a/ldso/dynlink.c    2022-04-07 19:12:40.000000000 +0200
+++ b/ldso/dynlink.c    2023-04-16 20:40:15.960873385 +0200
@@ -1791,7 +1791,15 @@
                int fd;
                char *ldname = argv[0];
                size_t l = strlen(ldname);
-               if (l >= 3 && !strcmp(ldname+l-3, "ldd")) ldd_mode = 1;
+               if (l = 3 && !strcmp(ldname, "ldd"))
+               {
+                   ldd_mode = 1 ;
+               }
+               else
+               if ( l = 8 && !strcmp(ldname, "musl-ldd"))
+               {
+                   ldd_mode = 1 ;
+               }
                argv++;
                while (argv[0] && argv[0][0]=='-' && argv[0][1]=='-') {
                        char *opt = argv[0]+2;

Additionaly the Makefile would have to be adjusted, to create a
symbolic link at

    $(bindir)/musl-ldd  ->  $(libdir)/libc.so

Required patch :

--- a/Makefile    2022-04-07 19:12:40.000000000 +0200
+++ b/Makefile    2023-04-16 21:42:00.000000000 +0200
@@ -219,6 +219,7 @@
 install-tools: $(ALL_TOOLS:obj/%=$(DESTDIR)$(bindir)/%)
 
 install: install-libs install-headers install-tools
+       ln -sv $(libdir)/libc.so $(DESTDIR)$(bindir)/musl-ldd
 
 musl-git-%.tar.gz: .git
         git --git-dir=$(srcdir)/.git archive --format=tar.gz --prefix=$(patsubst %.tar.gz,%,$@)/ -o $@ $(patsubst musl-git-%.tar.gz,%,$@)


This way, the same musl build can be used on the development
machine where it has to co-exist at least with glibc and the
target machine, where musl is the standard (and only) linker.

I have to admit, that the dynlink.c file could stay as it
is, because right now it accepts any program name, which
ends with "ldd". This might be intended behaviour.

But at least for me, it would simply feel wrong and I
prefer source code, which is explicit about certain
things.

In that regard, the text in the FAQ might also be changed,
because

    Just create a symlink from ld-musl-$ARCH.so to /bin/ldd.

would be more correctly

    Just create a symlink
        /bin/<whatever>ldd
    pointing to
        ld-musl-$ARCH.so.

Because, for example, a link created as

    /usr/bin/paldd  ->  $(libdir)/libc.so

would also work and I see no 'musl' in 'paldd', hence
my comment about software being explicit.


2.  Only install the symbolic link 'musl-ldd' with the
    Makefile patch above.


I tested both variants with success and use solution #1
in production.


Best regards,

Lorenz Hipp




References :

[1] https://github.com/archlinux/svntogit-community/blob/packages/musl/trunk/PKGBUILD




P.S. :

For the sake of completeness, my musl is built and installed with

    ./configure --prefix=/usr/lib/musl \
                --exec-prefix=/usr \
                --enable-wrapper=all \
                CFLAGS="-ffat-lto-objects"
    make -w -j 16
    make -w -j 1 DESTDIR=/tmp/destroot install
    
    mv -v   /tmp/destroot/lib/ld-musl*.so* /tmp/destroot/usr/lib/
    rmdir   /tmp/destroot/lib
    
    install -Dvm644 README /tmp/destroot/usr/share/doc/musl-1.2.3/README
    
    # (archive and install afterwards as root)




Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.