Bash knows nothing about ELF. It simply sees that you asked it to run an external program, so it passes the name you gave it as-is to
execve(2). Knowledge of things like executable file formats, shebang lines, and execute permissions lives behind that syscall, in the kernel.
(It is the same for other shells, though they may choose to use another function in the
exec(3) family instead.)
In Bash 4.3, this happens on line 5195 of
execute_cmd.c in the
If you want to understand Linux at the source code level, I recommend downloading a copy of Research Unix V6 or V7, and going through that rather than all the complexity that is in the modern Linux systems. The Lions Book is a good guide to the code.
V7 is where the Bourne shell made its debut. Its entire C source code is just a bit over half the size of just that one C file in Bash. The Thompson shell in V6 is nearly half the size of the original Bourne shell. Yet, both of these simpler shells do the same sort of thing as Bash, and for the same reason. (It appears to be an
execv(2) call from
texec() in the Thompson shell and an
execve() call from
execs() in the Bourne shell's