I discussed whether I should dive into a broad question that leads to stubborn answers. Usually I vote to close such a question, but in this case I am going to offer an answer that may be useful to others. If you ask why? I am doing this on this issue - history has shown on Stackoverflow that this question is often indirectly asked as part of a more specific OS development question.
Some benefits of ELF for the kernel?
- Debugging information can be embedded in an object.
- The ELF loader can adjust the image in memory, automatically disable the BSS section, etc.
- Uninitialized or zero initialized global data does not take up space inside the image.
- Multitask loaders (e.g. GRUB) can load properly designed ELF executables
- It can be designed to be movable.
Disadvantages?
- ELF headers are placed at the beginning of the executable file, which may interfere with the intended target environment in which the executable executable is running (for example, loaders)
- For small programs, ELF headers may be too large for some applications (loaders)
- Requires code (minimal ELF loader) to load the executable into memory and start executing it.
Why don't we use ELF for the final boot sector image (MBR)?
The main reason is that the ELF format puts header information in front of the code. Outdated BIOSes (not EFIs) will not understand this and will begin to execute header information as code.
Can you use ELF images to debug a 16-bit bootloader?
It depends on the environment and the debugger. With remote debugging of GDB in QEMU, this is very possible. You can generate a 16-bit real-mode executable in assembler, such as NASM / GAS, etc. As an ELF object (with Dwarf debugging information), associate it with the final ELF executable, and then use a program such as objcopy to disable the ELF headers before generating the final flat binary.
Why worry about creating ELF objects for the loader if you split it into a flat binary anyway?
Although a headless binary will work in the target environment, an environment with remote debugging capabilities, such as QEMU, can use a local ELF binary to resolve variable names, labels, constants and allow source source navigation (not just raw editing) .
Can you give an example of this technique for 16-bit debugging?
Yes, this type of problem appeared earlier. I gave answers that show how to do this with the remote GDB debugging services and the remote debugger in QEMU. One such example can be found in this fooobar.com/questions/996631 / .... An example is an example of a 16-bit bootloader that can be debugged using GDB. 16-bit debugging is problematic with GDB because it does not understand pairs of segments: offset in 16-bit code. The link is provided by a script that helps in this regard, as well as an example of using QEMU.
Is there any advantage to running ELF when used with the Multiboot bootloader?
Yes! One big advantage for multiboot compatible downloaders such as GRUB is that it understands ELF images. If you write a kernel with protected mode and you use a properly designed Multiboot compatible executable for your kernel, you can save on the hard work (on x86 systems) of setting up a protected mode environment, resolving the A20 Gate, getting a memory card, and initializing video mode in startup mode.
Can QEMU run ELF kernel executable with multiboot support?
Yes, with the appropriate command line, using the -kernel option is possible. There is an example in the Dev Wiki OS .
Is it possible to debug 32-bit protected mode using ELF binaries with debugging information?
Yes, this is easier than doing this for 16-bit boot loaders that work in real mode. I offer an example of this technique in this fooobar.com/questions/996631 / .... Although an ISO image is used for QEMU, you can alternatively load QEMU with your multitasking kernel directly using the -kernel option.
Why do modern versions of Linux use the ELF format for the kernel?
In the ancient days of Linux development, Linux had its own bootloader, configured secure mode, including the A20 gate, etc. This process is different from architecture. The time came when the Linux kernel developers decided to leave this work to a third-party loader.
On modern desktop systems, you will find GRUB used as the Muliboot bootloader; ELILO can be used; on some embedded systems, U-Boot has become the bootloader's choice. The Multiboot specification arose because of the need to boot the Linux kernel, but regardless of the OS. Many Internet toy core examples are encoded for use as ELF executables so that they can take advantage of the benefits that Multiboot compatible bootloaders can offer.
For more information on the Multiboot specification, see the GRUB Documentation.