Bei der Arbeit an einem kleinen 32-Bit-Kernel für die x86-Architektur entdeckte ich etwas seltsam mit wie ld
behandelt Nobits Abschnitte.ld ignoriert Größe von Nobits Eingabeabschnitt
In meinem Kernel definiere ich einen .bootstrap_stack
Abschnitt, der einen temporären Stapel für den Initialisierungsteil des Systems enthält. Ich halte auch Symbole für den Anfang und das Ende des Stapels. Dieser Eingabebereich wird zum Ausgabebereich .bss
umgeleitet. Jeder Ausgabeabschnitt meines Kernels hat ein Symbol für den Anfang und das Ende des Abschnitts.
Das Problem ist, dass in der endgültigen ausführbaren Datei das Symbol für das Ende des Stapels ist nach das Ende der .bss
Abschnitt. In den folgenden Beispielen haben die Symbole stack_top
und _kernel_ebss
(und _kernel_end
) den gleichen Wert, was ich nicht wollte.
Ich erwartete _kernel_ebss
gleich stack_bottom
.
Jedoch einmal ich .bootstrap_stack
zu .bss
umbenennen, geschieht dies nicht. Entfernen nobits
funktioniert auch, aber die resultierende Binärdatei ist erheblich größer.
Hier sind die abgestreiften Dateien, die mein Problem zu reproduzieren:
boot.s
section .bootstrap_stack, nobits ; this does not work
;section .bootstrap_stack ; this works
;section .bss ; this also works
stack_top:
resb 8096
stack_bottom:
section .text
global _start
_start:
hlt
jmp _start
linker.ld
ENTRY(_start)
SECTIONS
{
. = 0xC0100000;
_kernel_start = .;
.text ALIGN(4K) : AT(ADDR(.text) - 0xC0000000)
{
_kernel_text = .;
*(.multiboot)
*(.text)
_kernel_etext = .;
}
.bss ALIGN(4K) : AT(ADDR(.bss) - 0xC0000000)
{
_kernel_bss = .;
*(COMMON)
*(.bss)
*(.bootstrap_stack)
_kernel_ebss = .;
}
_kernel_end = .;
}
Hier werden die Symbole:
$ objdump -t kernel | sort
00000000 l df *ABS* 00000000 boot.s
c0100000 g .text 00000000 _kernel_start
c0100000 g .text 00000000 _kernel_text
c0100000 g .text 00000000 _start
c0100000 l d .text 00000000 .text
c0100003 g .text 00000000 _kernel_etext
c0101000 g .text 00000000 _kernel_bss
c0101000 g .text 00000000 _kernel_ebss
c0101000 g .text 00000000 _kernel_end
c0101000 l .bootstrap_stack, 00000000 stack_top
c0101000 l d .bootstrap_stack, 00000000 .bootstrap_stack,
c0102fa0 l .bootstrap_stack, 00000000 stack_bottom
Durch Umbenennen von .bootstrap_stack
zu .bss
Ich bekomme, was ich erwartet habe.
00000000 l df *ABS* 00000000 boot.s
c0100000 g .text 00000000 _kernel_start
c0100000 g .text 00000000 _kernel_text
c0100000 g .text 00000000 _start
c0100000 l d .text 00000000 .text
c0100003 g .text 00000000 _kernel_etext
c0101000 g .bss 00000000 _kernel_bss
c0101000 l .bss 00000000 stack_top
c0101000 l d .bss 00000000 .bss
c0102fa0 g .bss 00000000 _kernel_ebss
c0102fa0 g .bss 00000000 _kernel_end
c0102fa0 l .bss 00000000 stack_bottom
Meine Frage ist, ob dies das erwartete Verhalten von ld ist. Wenn ja, was ist das Problem mit meinem Beispiel, denn soweit ich weiß .bss
ist auch ein Nobits-Abschnitt, aber es produziert das erwartete Ergebnis?