Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: Developer30 am 01. August 2013, 13:14
-
Hallo Allerseits,
das ganze ist noch Neuland für mich, also habe ich mich an dem Artikel http://www.lowlevel.eu/wiki/C%2B%2B-Kernel_mit_GRUB (http://www.lowlevel.eu/wiki/C%2B%2B-Kernel_mit_GRUB) orientiert. Ich habe alle Anweisungen auf der Seite befolgt und das ganze mal kompiliert und mit bochs ausgeführt. Ich musste feststellen, dass das screen Objekt, was global in der Video.cpp erstellt wird, scheinbar nicht über den Konstruktor initialisiert wurde, weil auf dem Bildschirm nichts passiert. Wenn ich ein Video Objekt hingegen in der kernelMain Funktion erstelle, dann funktioniert die Bildschirmausgabe. Ich weiß nicht, was ich falsch gemacht haben soll. Eigentlich sollten doch alle Konstruktoren von globalen und statischen Objekten mit der initialiseConstructors Funktion aufgerufen werden. Die Startup.cpp sieht bei mir so aus:
typedef void (*constructor)();
// Im Linkerskript definiert
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" void initialiseConstructors();
// Ruft die Konstruktoren für globale/statische Objekte auf
void initialiseConstructors()
{
for (constructor* i = &start_ctors;i != &end_ctors;++i)
(*i)();
}
Das einzig Auffällige ist die Warnung, die beim kompilieren erscheint (ich glaube, mit dem Problem hat die Warnung allerdings nicht viel zutun):
Kernel.cpp:8:6: Warnung: unbenutzter Parameter »multiboot_structur« [-Wunused-parameter]
lg
Developer30
-
Einen offensichtlichen Fehler sehe ich nicht, also muss ich mal die ganz dumme Frage stellen: initialiseConstructors() wird schon auch irgendwo aufgerufen?
Ansonsten könntest du mal versuchen, ein bisschen Debugcode in die Funktion einzubauen, dass du siehst, welche Konstruktoren (falls überhaupt) er aufruft. Nur vielleicht nicht grad mit der Video-Klasse, die wäre für die Ausgaben nützlich... Du kannst auch mal mit objdump/readelf oder so anschauen, ob deine ctors-Section überhaupt einen Inhalt hat und ob das der erwartete ist.
-
initialiseConstructors() wird schon auch irgendwo aufgerufen?
ja, es wird in der asmKernel.asm aufgerufen, unmittelbar bevor die kernelMain aufgerufen wird.
loader:
mov esp,0x200000
push eax
push ebx
call initialiseConstructors ; Konstruktoren aufrufen
call kernelMain ; kernelMain aufrufen
Ansonsten könntest du mal versuchen, ein bisschen Debugcode in die Funktion einzubauen, dass du siehst, welche Konstruktoren (falls überhaupt) er aufruft.
Wie kann ich mir das denn am besten ausgeben lassen?
Du kannst auch mal mit objdump/readelf oder so anschauen, ob deine ctors-Section überhaupt einen Inhalt hat und ob das der erwartete ist.
Ich habe noch nie mit objdump gearbeitet (also sorry falls ich da jetzt was falsch verstehe). Ich habe mir mal mit objdump -h kernel.bin alle sections angezeigt.
$ objdump -h kernel.bin
kernel.bin: Dateiformat elf32-i386
Sektionen:
Idx Name Größe VMA LMA Datei-Off Ausr.
0 .text 00000370 00100000 00100000 00001000 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .eh_frame 000001b8 00100370 00100370 00001370 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .init_array 00000004 00100528 00100528 00001528 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .fini_array 00000004 0010052c 0010052c 0000152c 2**2
CONTENTS, ALLOC, LOAD, DATA
4 .bss 00000010 00100530 00100530 00001530 2**2
ALLOC
Wenn ich das richtig verstanden habe, müsste es doch auch eine .data section geben, wo dann start_ctors und end_ctors drin sein müsste, oder nicht?
-
In .init_array müssten die Konstruktor-Pointer sein, glaube ich. Ob dein Linkerskript start_ctors und end_ctors passend anlegt, musst du selber wissen.
Dass es kein .data gibt, sieht in der Tat komisch aus und könnte auch wieder auf ein Problem mit dem Linkerskript hinweisen, allerdings sind die beiden Symbole nichts, was nach .data gehört. Vielleicht hast du aber auch einfach nichts in .data (dort landen z.B. initialisierte globale Variablen).
-
Neuere GCC Versionen erzeugen keine ctros-sections mehr sondern init_array und fini_array sections. D.h. deine ctors liste bleibt vermutlich leer (start/end-ctors sind gleich).
nm kernel.elf | grep ctors
Du kannst dir die ctors / dtors etwa so in deinem linkscript zusammen sammeln. (statt dem .ctors* .*dtors zeug wie es im Tutorial steht)
__init_array = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
__init_array_end = .;
/* List all Destructors here */
__fini_array = .;
KEEP(*( .fini_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .fini_array.* )));
__fini_array_end = .;
__init_array entspricht dann start_ctors etc.
-
Danke für eure Hilfe Kevin und MNemo.. Die linkscript Lösung von MNemo hat das Problem gefixt. Danke :wink:
-
MNemo, magst du das zufällig ins Wiki packen? :)