1

from the musl libc FAQ

Q: Where is ldd?

musl’s dynamic linker comes with ldd functionality built in. Just create a symlink from ld-musl-$ARCH.so to /bin/ldd. If the dynamic linker was started as “ldd”, it will detect that and print the appropriate DSO information.

Inspecting ld-musl-$ARCH.so I found that it's a symlink to the musl /usr/local/musl/lib/libc.so

and that is definitely a shared library

$ file /usr/local/musl/lib/libc.so
/usr/local/musl/lib/libc.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=068deca2fec0ea2c50ec1e11166d25b3bb057431, not stripped

And it actually works which is nuts lol. I can actually do this:

$ /usr/local/musl/lib/libc.so ./a.out

And it will work. But how is it possible that I can invoke a shared library from the terminal?

Community
  • 1
  • 1
Adham Zahran
  • 1,973
  • 2
  • 18
  • 35
  • 3
    Possible [cross-site duplicate](https://unix.stackexchange.com/questions/223385/why-and-how-are-some-shared-libraries-runnable-as-though-they-are-executables) – that other guy Jul 16 '19 at 23:51
  • 3
    Related [Why and how are some shared libraries runnable, as though they are executables?](https://unix.stackexchange.com/questions/223385/why-and-how-are-some-shared-libraries-runnable-as-though-they-are-executables) – David C. Rankin Jul 16 '19 at 23:52

1 Answers1

2

Okay I think I understand.

So basically a shared library is in fact an executable. And because musl is a libc implementation it defines the _start() function which is the real entry-point of the program. The _start() function would then calls the main function.

The developers of musl made it so that if you invoke their libc.so as ld or ldd they would detect that and act accordingly.

They can detect that because _start() does take argc and argv (which would then be passed on to main()) so they can see if argv[0] is "ld" or "ldd".

And thanks to @that other guy and @David C. Rankin for linking this. The answer there says that you can even have a shared library that defines main().

So I tried that myself.

Here's _start.c

void
_start()
{
    asm("mov $60,%rax; mov $0,%rdi; syscall");
}

I compiled that on an x86_64 ubuntu linux machine with gcc 7.4.0 like so:

$ gcc -shared -nostdlib _start.c -o libwow.so

And then I called it:

$ ./libwow.so
$

It didn't do anything of course, but it did run.

It's a crazy world we live in :D

EDIT:

On a crazier note. One can load executables as dynamic libraries using dlopen(3). Look at this answer to learn more.

Conclusion:

Shared libraries and Executables are pretty much the same thing (ELF binaries).

Except that shared libs have no fixed entry-point address while executables do.

Also shared libs are PIE while binaries are not by default.

And I guess there are a few other minor differences :p

There are executables (traitors :p) that live among us that were really shared libs all along and we didn't know like gawk and ntfsck.

Look at this Question/Answers for more information.

Adham Zahran
  • 1,973
  • 2
  • 18
  • 35