Ah sorry, I should have been more clear. So ET_EXEC
or ET_DYN
is just the kind of binary in the ELF header struct (the e_type
field), or if you run readelf -e
or objdump -f
it’ll have similar output.
So readelf -e /bin/ls
will show the type as EXEC
, whereas if you run it on a rustc binary compiled with the standard toolchain on linux (i.e. just rustc main.rs
), readelf -e main
should report DYN
.
A PIE is just a shared object (DLL, dynamic library, or ET_DYN
) with an entry point, so it can be loaded anywhere in memory (and thus can take advantage of ASLR) and executed. For example, this is a requirement on the android platform now iirc.
So grepping through liblibc-<hash>.rlib
and my libc.a
from compiling musl the rustlib has the problematic R_X86_64_32S
relocation, but the libc.a
does not.
After spending a bunch of time on this I just realized that I originally had this problem a while back, and I added this line into the musl ./configure
in my make_static.sh
script which was adopted from the chapter on advanced linking, and which essentially mirrors your build setup:
CFLAGS=-fPIC ./configure --disable-shared --prefix=$PREFIX
I’ve just tested, and if I build musl without the CFLAGS=-fPIC
environment variable given to configure (i.e., ./configure --disabled-shared
and not CFLAGS=-fPIC ./configure --disable-shared
) then it will have those problematic relocations.
So, your initial intuition was correct!
Additionally if you look at the musl Makefile
, you’ll see that if passes -fPIC
to the shared object (which we disable):
$(LOBJS) $(LDSO_OBJS): CFLAGS_ALL += -fPIC
but not to the static libc version :]
The above CFLAG=-fPIC
is an ugly hack, but it seems to work for me.
I believe you can also add this line in the musl Makefile
(but it’s more invasive):
$(AOBJ): CFLAGS_ALL += -fPIC
How is the liblibc-<hash>.rlib
generated? I’d like to create the artifact with the -fPIC
'd libc.a to verify it works correctly, etc.