Re:ELF files on Linux
by kccqzy on Thursday May 16, 2019 @04:04PM
(#19932545)
One thing that's on my mind but haven't been able to spend time investigating is the fact that on my machine (Ubuntu 19.04), almost all distribution-installed executables are not ELF executables per se, but ELF shared objects. Running `file /bin/ls` shows that it's an ELF 64-bit LSB shared object. Running `readelf -h /bin/ls` also says that the type is DYN. Is the executable type basically deprecated now?
[ Parent
| on HN ]
Position Independant Executable (PIE) files are detected as shared libraries because they use the same old identifier as position independent shared libraries. The ELF folks could have added a new type but did not, leading to some confusion like this: https://bugs.launchpad.net/ubuntu/+source/shared-mime-info/+...
PIE is a security feature, which is why it has proliferated on newer systems. See https://access.redhat.com/blogs/766093/posts/1975793
Here is an example to try and see yourself:
$ cat show-addr.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("main() is at %p\n", main);
}
$ gcc -o show-addr show-addr.c
$ file show-addr
show-addr: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=60c8b61a7040adccc90934bc79e24342eecae15a, not stripped
$ ./show-addr
main() is at 0x400526
$ ./show-addr
main() is at 0x400526
$ gcc -pie -fPIC -o show-addr.pie show-addr.c
$ file show-addr.pie
show-addr.pie: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=73ae8065a65aad4b829567b7ce3464fb5d1e3fc3, not stripped
$ ./show-addr.pie
main() is at 0x55c722ae1750
$ ./show-addr.pie
main() is at 0x5649bf97b750
$
(edit: incomplete copy-paste fixed)A somewhat lesser known but (IMO) fun fact is that if you compile your executable with -export-dynamic, you can dlopen it and dlsym for functions inside of it just like you would with any other shared library (note that if your goal is to just load the executable, such as if it already has a constructor defined, you don't even need this flag).