Skip to content

Commit

Permalink
Place "multiboot" section right after the ELF header
Browse files Browse the repository at this point in the history
This is an experimental feature to support Multiboot specification.

#563
  • Loading branch information
rui314 committed Oct 25, 2022
1 parent 997e534 commit 4db7574
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 27 deletions.
64 changes: 37 additions & 27 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1332,10 +1332,11 @@ void clear_padding(Context<E> &ctx) {

// We want to sort output chunks in the following order.
//
// ELF header
// program header
// <ELF header>
// multiboot
// <program header>
// .interp
// alloc note
// .note
// .hash
// .gnu.hash
// .dynsym
Expand All @@ -1344,23 +1345,30 @@ void clear_padding(Context<E> &ctx) {
// .gnu.version_r
// .rela.dyn
// .rela.plt
// alloc readonly data
// alloc readonly code
// alloc writable tdata
// alloc writable tbss
// alloc writable RELRO data
// <readonly data>
// <readonly code>
// <writable tdata>
// <writable tbss>
// <writable RELRO data>
// .got
// .toc
// alloc writable RELRO bss
// <writable RELRO bss>
// .relro_padding
// alloc writable non-RELRO data
// alloc writable non-RELRO bss
// nonalloc
// section header
// <writable non-RELRO data>
// <writable non-RELRO bss>
// <non-memory-allocated sections>
// <section header>
//
// The reason to place .interp and other sections at the beginning of
// a file is because they are needed by the loader. Especially on a
// hard drive with spinnning disks, it is important to read these
// If a section whose name is "multiboot" exists, it's placed right
// after the ELF header. We do this for OS kernels. "multiboot" section
// is expected to be read-only, start with a magic number and have an
// alignment requirement of 32. GRUB (and other Multiboot specification-
// compliant bootloaders) can recognize such data strcuture near the
// beginning of a file and load a file into memory.
//
// .interp and some other linker-synthesized sections are placed at the
// beginning of a file because they are needed by loader. Especially on
// a hard drive with spinnning disks, it is important to read these
// sections in a single seek.
//
// .note sections are also placed at the beginning so that they are
Expand Down Expand Up @@ -1395,28 +1403,30 @@ void sort_output_sections(Context<E> &ctx) {

if (chunk == ctx.ehdr)
return 0;
if (chunk == ctx.phdr)
if (chunk->name == "multiboot")
return 1;
if (chunk == ctx.interp)
if (chunk == ctx.phdr)
return 2;
if (type == SHT_NOTE)
if (chunk == ctx.interp)
return 3;
if (chunk == ctx.hash)
if (type == SHT_NOTE)
return 4;
if (chunk == ctx.gnu_hash)
if (chunk == ctx.hash)
return 5;
if (chunk == ctx.dynsym)
if (chunk == ctx.gnu_hash)
return 6;
if (chunk == ctx.dynstr)
if (chunk == ctx.dynsym)
return 7;
if (chunk == ctx.versym)
if (chunk == ctx.dynstr)
return 8;
if (chunk == ctx.verneed)
if (chunk == ctx.versym)
return 9;
if (chunk == ctx.reldyn)
if (chunk == ctx.verneed)
return 10;
if (chunk == ctx.relplt)
if (chunk == ctx.reldyn)
return 11;
if (chunk == ctx.relplt)
return 12;

bool writable = (flags & SHF_WRITE);
bool exec = (flags & SHF_EXECINSTR);
Expand Down
11 changes: 11 additions & 0 deletions test/elf/multiboot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash
. $(dirname $0)/common.inc

cat <<EOF | $CC -o $t/a.o -c -xc - -fPIC
__attribute__((section("multiboot"), aligned(32)))
const char hdr[32] = {0};
void _entry() {}
EOF

./mold -o $t/exe $t/a.o --image-base=0x100000
readelf -SW $t/exe | grep -q 'multiboot.*0100040'

0 comments on commit 4db7574

Please sign in to comment.