I have two questions highlighted below. I'm using 64-bit Linux.
I saw on another post that MUSL was mentioned as a libc implementation.
I tried using this with the following Hello world assembly program that uses two libc functions, write and _exit.
.data
hello:
.ascii "Hello, world\n"
.text
.globl _start
_start:
movl $13, %edx
movl $hello, %esi
movl $1, %edi
call write
movl $0, %edi
call _exit
I assembled the code with:
# Command 1
$ as -o hello.o hello.s
I then ran ld to generate an executable that statically links MUSL libc.
# Command 2
$ ld hello.o /usr/lib/x86_64-linux-musl/libc.a
That generated an a.out file that works as expected, outputting "Hello, world" when executed.
I also tried a different invocation of the preceding ld command, using -static -lc instead of specifying the path directly, and also using -L to give the path to MUSL so that glibc is not used, since the latter is already on ld's search path.
# Command 3
$ ld hello.o -L/usr/lib/x86_64-linux-musl/ -static -lc
That worked as expected.
Next I tried to dynamically link MUSL libc.
# Command 4
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 hello.o \
/usr/lib/x86_64-linux-musl/libc.so
That appears to work as expected. I can run a.out, and calling ldd on a.out shows that MUSL's libc is linked.
Lastly, I tried an analogous modification relative to the statically linked version earlier, using -lc and -L instead of specifying the path to the .so file directly.
# Command 5
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 hello.o \
-L/usr/lib/x86_64-linux-musl -lc
The program does not run properly, outputting the error:
bash: ./a.out: No such file or directory
When I run that same ld command with the --verbose flag, the output is the same as when passing --verbose to the earlier ld command (Command 4 that generated a working executable).
Running ldd on a.out also outputs an error:
./a.out: error while loading shared libraries: /usr/lib/x86_64-linux-gnu/libc.so: invalid ELF header
Question 1: Why does calling ld with -L and -lc in this case not match the behavior from earlier, where I specified the .so file directly?
I noticed that if I change the specified dynamic linker to /lib/ld-musl-x86_64.so.1, the generated a.out runs as expected.
# Command 6
$ ld -dynamic-linker /lib/ld-musl-x86_64.so.1 hello.o \
-L/usr/lib/x86_64-linux-musl -lc
However, calling ldd on the generated a.out produces the following error, which was not the case earlier when I did not use -lc and -L in Command 4:
./a.out: error while loading shared libraries: /usr/lib/x86_64-linux-gnu/libc.so: invalid ELF header
Question 2: Why does ld fail on this binary, but worked earlier when I passed the path of the .so file to ldd and used a different dynamic linker?