Autor Thema: Executable Loader  (Gelesen 9897 mal)

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« am: 13. December 2010, 20:39 »
Hallo zusammen,
nachdem ich meinen Floppy / Fat Treiber fertig hatte, wollte ich jetzt auch mal Dateien in laden und starten. In Teil 8 des Tutorials, wurde ein ELF-Loader erklärt. Den habe ich auch funktionsfähig (zumindest bei von GRUB übergebenen Modulen) implementiert. Jetzt habe ich vor, die Daten, die ich von der Floppy gelesen habe, als ELF zu starten.
Das Problem ist, dass ich bekomme, wenn ich die ELF Datei starte, einen Invalid Opcode bekomme.
char app[size]; //Speicher reservieren
kmemset((void*) &app[0], 0x0, size);//Speicher zu sicherheit putze
readFile( f, size, &app[0] ); //Von der Floppy einlesen
char *appP = &app[0]; //Sonst funktioniert es nicht....
initELF( (void*) appP, 20); //ELF Datei laden
Dazu der ELF Loader:

void *initELF(void* image, int pri)
{
    /*
     * FIXME Wir muessen eigentlich die Laenge vom Image pruefen, damit wir bei
     * korrupten ELF-Dateien nicht ueber das Dateiende hinauslesen.
     */
 
    struct elf_header* header = image;
    struct elf_program_header* ph;
    int i;
 
    /* Ist es ueberhaupt eine ELF-Datei? */
    if (header->magic != ELF_MAGIC) {
        kprintf("Keine gueltige ELF-Magic!\n");
        return 0;
    }
 
    /*
     * Alle Program Header durchgehen und den Speicher an die passende Stelle
     * kopieren.
     *
     * FIXME Wir erlauben der ELF-Datei hier, jeden beliebigen Speicher zu
     * ueberschreiben, einschliesslich dem Kernel selbst.
     */
    ph = (struct elf_program_header*) (((char*) image) + header->ph_offset);
    for (i = 0; i < 2/*header->ph_entry_count*/; i++, ph++) {
        void* dest = (void*) ph->virt_addr;
        void* src = ((char*) image) + ph->offset;
 
        /* Nur Program Header vom Typ LOAD laden */
        if (ph->type != 1) {
            continue;
        }
 
        kmemset(dest, 0, ph->mem_size);
        kmemcpy(dest, src, ph->file_size);
    }
 initTask( (void *)header->entry, pri);
    return (void*) header->entry;
}
Ich musste
header->ph_entry_count gegen 2 austauschen, weil der Wert bei ungefähr 30 000 liegt.

Die ELF Datei lädt er auch, aber sobald ich einen Syscall von dem ausgeführten Programm aufrufe, geschieht der Invalid Opcode.

Hat einer von euch eine Idee?
S.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 13. December 2010, 21:01 »
Ich schätze mal, es geht irgendwas beim Einlesen schief. Wenn du schon ein Feld im Header nicht benutzen kannst, weil Müll drinsteht, wird ganz sicher auch in anderen Feldern oder im Programm selbst Müll stehen. ;)

Ich würde mir mal einen Hexdump von dem geladenen ELF-Image ausgeben lassen und dann mit der richtigen ELF-Datei vergleichen.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 13. December 2010, 22:21 »
Hallo,


nur so als Gedanke:  sicher das der Speicher in den die ELF-Datei kommt korrekt gemappt ist, könnte ja sein das da was anderes drin liegt als erwartet.

Ein Hex-Dump der ersten 256 Bytes der geladenen ELF sollte wirklich Licht ins Dunkel bringen können.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #3 am: 14. December 2010, 09:04 »
@taljeth: Die ELF Magic ist aber immer noch funktionsfähig. Sonst er ja hier abstürzen:if (header->magic != ELF_MAGIC) {
   kprintf("Keine gueltige ELF-Magic!\n");
   return 0;
}
Aber er kann ja auch später abstürzen.
@erik.vikinger: Der gesammte hexdump liegt hier. Ist die ELF Datei evt. korrupt?

S.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 14. December 2010, 11:29 »
Hallo,


Die ELF Magic ist aber immer noch funktionsfähig.
Die Datei ist aber größer als eine Page, möglicherweise sind die Probleme weiter hinten.

@erik.vikinger: Der gesammte hexdump liegt hier. Ist die ELF Datei evt. korrupt?
Das kann ich wirklich nicht beurteilen, ich kenne mich mit ELF nur sehr rudimentär aus. Die entscheidende Frage ist ob das was im Speicher vorliegt auch noch exakt das selbe ist was in der Datei drin ist. Du kennst doch die Größe der Datei, lass Deinen Datei-Loader die ermittelte Größe einfach mal ausgeben und vergleiche. Das nächste wäre eine Prüfsumme über die gesamte Datei (z.B. Adler32, die ist simpel und hierfür ausreichend und reagiert auch auf unterschiedlich lange Folgen von 0-Bytes). Wenn die Größe und die Check-Summe noch stimmen kannst du wenigstens sicher sein das die Datei korrekt und vollständig geladen wurde und der Speicher dafür richtig funktioniert. Als nächstes musst Du dann das Relozieren prüfen, dafür muss der Code der ELF-Datei für den Kernel modifizierbar sein.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Programm Noob

  • Gast
Gespeichert
« Antwort #5 am: 14. December 2010, 12:58 »
Was passiert, wenn du genau die gleiche elf Datei von GRUB laden lässt? geht es dann? wenn ja, dann scheidet die elf Datei als Fehler aus. dann kann es wie schon gesagt am Paging liegen.

PNoob

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 14. December 2010, 15:51 »
GRUB lädt nur den Kenel als ELF, und damit er das macht, braucht es auch noch einen Multibootheader, den ein Programm üblicherweise nicht hat...
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Programm Noob

  • Gast
Gespeichert
« Antwort #7 am: 14. December 2010, 20:05 »
Ich meinte als Multiboot modul. sollte man aus dem kontext herraus erkennen können.

PNoob

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #8 am: 14. December 2010, 22:20 »
GRUB überprüft nicht ob Multiboot Module gültige ELF Dateien sind.
Man kann genauso BMP's oder was ganz anderes Laden lassen.

LittleFox

Programm Noob

  • Gast
Gespeichert
« Antwort #9 am: 14. December 2010, 23:09 »
wollt ihr mich nicht verstehen?
Er soll sich die ELF Datei mit GRUB in den Speicher bevördern lassen und diese dann mit seinem ELF loader laden.

Das man mit Grub alles laden kann ist mir bewusst.
PNoob

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 14. December 2010, 23:26 »
@PNoob:
In Teil 8 des Tutorials, wurde ein ELF-Loader erklärt. Den habe ich auch funktionsfähig (zumindest bei von GRUB übergebenen Modulen) implementiert
Dieser Text wird unter jedem Beitrag angezeigt.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 15. December 2010, 12:01 »
Hallo,


In Teil 8 des Tutorials, wurde ein ELF-Loader erklärt. Den habe ich auch funktionsfähig (zumindest bei von GRUB übergebenen Modulen) implementiert
Genau deswegen denke ich dass das Problem eher beim Laden der ELF-Dateien in den Speicher (über den eigenen Dateisystemtreiber usw.) liegt und nicht beim ELF-Loader (Interpreter) der dann aus der ELF einen neuen Prozess baut.

Für genauere Analysen sind aber mehr Infos von spaceemotion erforderlich, alles andere ist pure Spekulation.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 15. December 2010, 13:09 »
char app[size]; //Speicher reservieren
Ich hoffe das ist nur eine Vereinfachung und liegt nicht wirklich auf dem Stack. Das wäre sonst die Erklärung warum es nicht funktioniert. Den Speicher dafür musst du mit einem vernünftigen Allokator reservieren.
Dieser Text wird unter jedem Beitrag angezeigt.

LittleFox

  • Beiträge: 306
    • Profil anzeigen
    • LF-Net.org
Gespeichert
« Antwort #13 am: 15. December 2010, 16:27 »
@PNoob sorry, wirklich anders verstanden

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #14 am: 19. April 2011, 20:40 »
Tut mir leid, dass ich solange nicht geschrieben haben. Ich musste sehr viel für meine Entwicklungsumgebung tun.
Ich mache jetzt gerade weiter. Die Datei ist komplett korrekt eingelesen. Die Adler32-Summen sind gleich.
Nachdem ich Paging eingebaut habe, erstelle ich für diesen Task (wie für jeden anderen auch) eine eigene Page. Nachdem Wechsel zum neuen Task, gibt es einen GPF.

Wäre nett, wenn sich nochmal jemand melde, obwohl ich solange nicht online war

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 19. April 2011, 21:30 »
Du erstellst für jeden Task eine Page? Dann wird der GPF wohl daher kommen, dass die zweite Page nicht oder falsch gemappt ist. Üblicherweise sind Programme nämlich größer als eine Page...

Gruß,
Svenska

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 21. April 2011, 19:37 »
und Programme (also eigenständige Prozesse) benötigen nicht nur eigene Pages sondern ein komplettes eigenes Paging-Directory das dann diese eigenen Pages verwaltet. ;)
Reality is that which, when you stop believing in it, doesn't go away.

spaceemotion

  • Beiträge: 49
    • Profil anzeigen
    • SpaceEmotion
Gespeichert
« Antwort #17 am: 22. April 2011, 18:44 »
Du erstellst für jeden Task eine Page? Dann wird der GPF wohl daher kommen, dass die zweite Page nicht oder falsch gemappt ist. Üblicherweise sind Programme nämlich größer als eine Page...

Gruß,
Svenska
So, das habe ich jetzt gelöst. Ich mappe genausoviel wie ich brauche. Ich mappe genau soviel wie mein Task braucht.
und Programme (also eigenständige Prozesse) benötigen nicht nur eigene Pages sondern ein komplettes eigenes Paging-Directory das dann diese eigenen Pages verwaltet. ;)
Und hier meinte ich eigentlich auch Pagedirectory und nicht Page. Danke für den Hinweis

Mein Loader funktioniert jedenfalls so wie ich das sehe. Vielen Dank, an alle die sich Gedanken gemacht haben

 

Einloggen