Autor Thema: relocatable kernel  (Gelesen 7647 mal)

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« am: 10. March 2011, 23:51 »
Hi,

ich habe mir mal Gedanken darueber gemacht, wie man am effektivsten einen Kernel schreiben kann, den man bei aktivem Paging auch komplett an eine andere Adresse legen kann.
Was muss man dabei denn alles beachten?

Auf jeden Fall muss man den Stack bearbeiten. Dabei faellt mir auf auf, dass es auch schief gehen kann, oder? Wenn auf dem Stack ein Wert steht, der in den Code-Bereich passt, obwohl es keine Adresse ist.
Dann muessen auch noch die aufgebauten Datenstrukturen umgelegt werden, oder?
Unter C ist das noch recht simpel, aber unter C++ ist das ungemein schwerer, oder?

Hat sich einer von euch schon mal daran versucht?

rizor
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 11. March 2011, 08:42 »
Hm, mal eine ganz blöde Frage: Wozu willst du denn den Kernel zur Laufzeit (also nach der Initialisierung) überhaupt relozieren? Mir fällt dafür kein vernünftiger Grund ein.

Selbst in C dürfte es ziemlich schwierig werden, alle Pointer zu erwischen, die ein Kernel irgendwo rumliegen hat, wenn es etwas mehr als ein Hello-World-Kernel sein soll. Blind alle Werte zu ersetzen, die wie ein Pointer aussehen klappt jedenfalls nicht, du brauchst schon die Information dazu, was für ein Datentyp es ist. Also müsstest du wohl manuell jeden einzelnen Pointer ändern, und das ist eine Garantie für Bugs.

Davon abgesehen bräuchtest du neben dem ausführbaren Kernel auch nochmal einen relozierbaren Kernel (also im Prinzip eine große Objektdatei) im Speicher, sonst wirst du schon am Ändern des Codes scheitern.
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

PNoob

  • Beiträge: 106
    • Profil anzeigen
    • Mein Blog
Gespeichert
« Antwort #2 am: 11. March 2011, 14:36 »
Moin

Hm, mal eine ganz blöde Frage: Wozu willst du denn den Kernel zur Laufzeit (also nach der Initialisierung) überhaupt relozieren? Mir fällt dafür kein vernünftiger Grund ein.
Naja grub kann den kernel ja nicht in adressen packen, wo man ihn aber vielleicht gerne hätte. zB. an die 4GB grenze.

Davon abgesehen bräuchtest du neben dem ausführbaren Kernel auch nochmal einen relozierbaren Kernel (also im Prinzip eine große Objektdatei) im Speicher, sonst wirst du schon am Ändern des Codes scheitern.
wie wärs mit einem Kleinem Startup Code, welcher alles initialisiert, den Kernel an die richtige adresse legt und dann in den eigentlichen kernel spring. dann kann man auch gleich ein bisschen Platz sparen.(Ich weiß das ist Sinnlos, weil es nur wenige kb sind.)

PNoob

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 11. March 2011, 15:20 »
Hallo,

Hm, mal eine ganz blöde Frage: Wozu willst du denn den Kernel zur Laufzeit (also nach der Initialisierung) überhaupt relozieren? Mir fällt dafür kein vernünftiger Grund ein.
Naja grub kann den kernel ja nicht in adressen packen, wo man ihn aber vielleicht gerne hätte. zB. an die 4GB grenze.
Dann muss der Kernel trotzdem nicht zur Laufzeit die Adresse wechseln.

wie wärs mit einem Kleinem Startup Code, welcher alles initialisiert, den Kernel an die richtige adresse legt und dann in den eigentlichen kernel spring. dann kann man auch gleich ein bisschen Platz sparen.(Ich weiß das ist Sinnlos, weil es nur wenige kb sind.)
Das ist was anderes, weil du damit den Kernel während der Initialisierung reloziierst. Die Adresse später, wenn bereits alles läuft, zu ändern, ist ungleich schwieriger.

Gruß,
Svenska

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 11. March 2011, 17:38 »
Genau, dafuer habe ich es mir gedacht.
Wollte meinen Kernel in das untere GB legen.
Dann werde ich mir mal einen geschickten start-up-code ueberlegen.

Danke fuer die Ideen
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #5 am: 11. March 2011, 18:53 »
Hm, mal eine ganz blöde Frage: Wozu willst du denn den Kernel zur Laufzeit (also nach der Initialisierung) überhaupt relozieren? Mir fällt dafür kein vernünftiger Grund ein.
Naja grub kann den kernel ja nicht in adressen packen, wo man ihn aber vielleicht gerne hätte. zB. an die 4GB grenze.
Wieso will man den Kernel nach so weit oben im RAM packen (vor allem, wenn man nicht weiß, wie viel RAM der Rechner hat)? :?

Zum Startupcode: Wieso nicht einfach gleich den Kernel an die gewünschte (virtuelle) Adresse linken und dann halt im Startupcode schnell Paging initialisieren¹? Ich kenne keinen Higher-Half-Kernel, der dafür relozierbar sein muss…

¹Da gibt es natürlich auch noch andere Wege, s. z. B. http://wiki.osdev.org/Higher_Half_Kernel.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 11. March 2011, 19:32 »
Hallo,


ich würde ja noch positionsunabhängigen Code vorschlagen, dann wäre es dem Kernel egal wo er liegt, aber ich weiß nicht ob Dein Compiler das kann.
Ich fürchte außerdem das geht bei x86 erst ab dem 64Bit-Long-Mode und nicht im 32Bit-PM.

Ansonsten denke ich auch das es das geschickteste wäre das Paging schon im Start-Up-Code zu aktivieren.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 11. March 2011, 22:01 »
@erik

Wie kommst du darauf, dass PIC erst ab x64 möglich ist? Wie funktionieren dann shared Libraries?

Das Problem mit PIC im PM ist, dass es ein Register (ebx) kostet und das nicht gerade vorteilhaft für die Performance ist.

Ansonsten habe ich auch einen relocatable Kernel und der Windows-Kernel kann das meiner Meinung nach auch. So schwer ist das eigentlich nicht. Wer nen ELF-Programm laden kann, sollte auch nen relocatable Kernel laden können.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #8 am: 11. March 2011, 23:15 »
Wie kommst du darauf, dass PIC erst ab x64 möglich ist? Wie funktionieren dann shared Libraries?
Anders als das, was er meint, nehme ich an. Der PIC bei x64 verwendet RIP-relative Adressierung, soweit ich weiß. Dadurch kann man Executables schreiben, die man irgendwo in den Speicher packen kann, wo sie dann einfach laufen. Bei x86 muss man im Allgemeinen eine Relocatable generieren, die erst von einem dynamischen Linker verarbeitet werden muss, bevor man sie ausführen kann. So funktionieren zumindest auch Shared Libraries.

Man kann natürlich auch auf x86 echten PIC schreiben, aber es gibt einen Unterschied zwischen Relocatables (Shared Libs) und PIC.

« Letzte Änderung: 11. March 2011, 23:17 von XanClic »

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 12. March 2011, 14:10 »
Das man unter x64 RIP-relative Code schreiben kann, weiß ich, aber ich bin mir eigentlich verdammt sicher das shared Libraries unter Linux PIC Code ist und da benutzt man keine relocatable´s. Das wird bei den DLL´s unter Windows genutzt. Der Vorteil ist das du die Libraries wirklich in jedem Prozess wiederverwenden kannst, egal wo sie hinkommen. Unter Windows müsstest du entweder die selben Adressen verwenden oder der Code muss doch in neuen Speicher gepackt werden, damit er geändert werden kann.

Guck dir mal GOT/PLT und sowas für ELF an.

Im PM nutzt man das ebx-Register für PIC, habe ich selbst auch schon in Assembler mal probiert, ist aber nicht so toll, weil ja das Register dann wegfällt.

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #10 am: 12. March 2011, 14:52 »
Das man unter x64 RIP-relative Code schreiben kann, weiß ich, aber ich bin mir eigentlich verdammt sicher das shared Libraries unter Linux PIC Code ist und da benutzt man keine relocatable´s.
Na gut. :-)

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 14. March 2011, 15:00 »
Hallo,


Man kann natürlich auch auf x86 echten PIC schreiben
Aber nur unter Hinnahme gewisser Einschränkungen wie z.B. den Verlust eines Registers. Allerdings bleiben dann noch so Probleme wie man den Pointer von einer Funktion bildet übrig (auf IP kann man ja nicht mal lesend zugreifen um z.B. den zur Compilezeit bekannten Abstand zu benutzen) oder wie eine C++-VTable befüllt werden soll. So ganz ohne Probleme ist echter PIC auf 32Bit-x86 nicht hinzubekommen wenn man den aktuellen Instruction-Pointer nicht einfach so als Quelle für Berechnungen oder als Offset für Speicherzugriffe hernehmen kann.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 14. March 2011, 15:21 »
@erik

Ist alles kein Problem ;)

Der Trick ist, dass man einfach einen call in die eigene Funktion macht und schon hat man die Adresse auf dem Stack!

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 14. March 2011, 15:58 »
Hallo,


Der Trick ist ....
Ja, den kenne ich, aber wirklich elegant oder zumindest bequem ist diese Lösung auch nicht gerade. Ich hab ja geschrieben das man gewisse Einschränkungen in Kauf nehmen muss um PIC auf klassischen x86 zu erhalten und diese Einschränkungen sind oft auch mit verminderter Performance verbunden.


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 14. March 2011, 17:09 »
@erik

Naja, dein Post ist ein wenig komsich formuliert. Weil ein Teil sagt, das man bestimmt Sachen nicht machen kann, aber das geht ja, kostet halt "nur" Performance.

Das ist übrigens auch ein sehr interessantes Thema. Was sollte man machen, seine shared-Libraries mit PIC laufen lassen und weniger Performance haben oder relocatable nutzen und so mehr Speicher benötigen?

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 14. March 2011, 18:33 »
Du kannst es wie Windows CE machen. Dort ist jede DLL an eine eigene Adresse gelinkt und jede DLL darf exakt ein einziges Mal im Speicher vorhanden sein. :-P

Bedenke, dass PIC nicht nur "weniger Performance" bedeutet, sondern auch "mehr Code". Ich habe vor langer Zeit mal was von 20-30% größerem Code gelesen (kann mich aber auch irren). Da lohnt sich relocatable direkt.

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 14. March 2011, 20:24 »
Wenn man seine shared-Libraries relocatable macht, dann verdienen sie ersten nicht mehr den Namen, shared und zweitens kostet es dann noch mehr Speicher und der steigt mit jeder Anwendung die diese Library nutzt.

Man muss also wie so oft, zwischen Speicherverbrauch und Performance abwägen.

Dass das mit immer an die gleiche Adresse laden nicht immer klappt, sollte aber klar sein. Man kann es nur so machen, wie es meiner Meinung nach unter Windows gemacht wird, dass die Library immer versucht wird an die selbe Adresse zu laden um die optimale Performance zu haben und trotzdem so wenig wie nötig Speicher zu verbrauchen.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 14. March 2011, 22:50 »
Ich glaube das stimmt aber auch nicht mehr so ganz. Ich bin der Meinung mal gelesen zu haben, dass Windows mittlerweile den Speicher randomisiert und dabei auch keine Ruecksicht auf Libraries nimmt. Kostet halt Speicher und ein wenig Performance, steigert die Systemsicherheit aber enorm.
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #18 am: 15. March 2011, 19:17 »
Hallo


Naja, dein Post ist ein wenig komsich formuliert.
Stimmt, sorry.

Das ist übrigens auch ein sehr interessantes Thema. Was sollte man machen, seine shared-Libraries mit PIC laufen lassen und weniger Performance haben oder relocatable nutzen und so mehr Speicher benötigen?
Oder besser eine CPU benutzen die PIC bei voller Performance erlaubt. ;)


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

FlashBurn

  • Beiträge: 844
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 15. March 2011, 20:55 »
Was eine andere CPU benutzen betrifft, unterstützen ARMs eigentlich die IP-relative Adressierung? Ansonsten bleibe ich vorerst bei den 32bit Architekturen und da muss ich auf x86 halt mit leben.

 

Einloggen