How does file(1) utility discern from an ELF shared object and an ELF executable?

Viewed 27

The problem is ELF shared libraries and normal executables don't differ at all if you look at their ELF headers. On my Linux machine(Debian 11.4) even e_type field of the ELF header is set to shared object file as ht utility reports even when the file in consideration is an ELF executable. It looked like the only easy and reliable method to differ ELF executable files from ELF shared libraries, and for some reason GCC fills out e_type field only with this value. Nevertheless, file(1) utility can accurately tell me if the input file I give to her is an executable or shared library.

The first answer to this question suggests that the file(1)'s code should look for PT_INTERP program header: distinguish shared objects from position independent executables

This sounds reasonable because all shared libraries get loaded after the executable file is loaded in first place, so they don't need to load interpreter one more time because a normal executable would already have done it.

Also I found this in file(1) source code when I was looking how magic.mgc file is compiled:

0   name        elf-le
>16 leshort     0       no file type,
!:mime  application/octet-stream
>16 leshort     1       relocatable,
!:mime  application/x-object
>16 leshort     2       executable,
!:mime  application/x-executable
>16 leshort     3       ${x?pie executable:shared object},

and I cannot understand what the last line means but it seems I can find an answer to my question if I understand this.

1 Answers
>16 leshort     3       ${x?pie executable:shared object},

This means "look at a 2-byte little endian word at offset 16 of the file. If it has the value '3' then check if the file is executable or not (permissions bit). If it is, the type is 'pie executable', otherwise it is 'shared object'"

You can look at the magic(5) man page for info about this syntax.

Related