HomeFreeBSD

Fix placement of __bss_start in i386 kernel linker script

Description

Fix placement of __bss_start in i386 kernel linker script

With lld 7.0.0, a rather nasty problem in our kernel linker script came
to light. We use quite a lot of so-called "orphan" sections, e.g.
sections which are not explicitly named in the linker script. Mainly,
these are the linker sets (such as set_sysinit_set).

Note that the placement of these orphan sections is not very well
defined. Usually, any read-only orphan sections get placed after the
last read-only section from the linker script, and similarly for the
read/write variants.

In our linker scripts, there are also symbol assignments like _etext,
_edata, and __bss_start, which are used in various places to refer to
the start or end addresses of sections.

However, some of these symbol assignments are interspersed with output
section descriptions. While the linker will guarantee that a symbol
assignment after some section will stay after that section, there is no
guarantee that an orphan section cannot be inserted just before it.

Take for example the following script:

SECTIONS
{

.data : { *(.data) }
__bss_start = .;
.bss : { *(.bss) }

}

If an orphan section (like set_sysinit_set) is now inserted just after
the bss_start assignment, bss_start will actually point to the start
of that orphan section, *not* to the start of the .bss section.

Unfortunately, something like this happened with our i386 kernel linker
script, and since sys/i386/i386/locore.s tries to zero .bss, it ended up
zeroing all the linker sets too, leading to a crash very soon after the
<--BOOT--> message.

To fix this, move the bss_start symbol assignment *into* the .bss
section description, so there is no way a linker can then insert orphan
sections at that point. Also add a corresponding
bss_end symbol.

In addition, change sys/i386/i386/locore.s, so it clears from
bss_start to bss_end, instead of assuming that _edata is just
before .bss (which may not be true), and that _end is just after _bss
(which also may not be true).

This allows an i386 kernel linked with lld 7.0.0 to boot successfully.

Details

Provenance
dimAuthored on
Parents
rS339316: Initialize SPRG0 before its first possible use.
Branches
Unknown
Tags
Unknown