ELF-Loader


  • Mod

    @Badestrand: Wie ist das, wenn mehrere Programme im ELF-Format "geladen" und gestartet werden sollen? Was muss man da bei deinem ELF-Loader beachten? z.B. bezüglich

    static const void* USERCODE_VADDR = (void*)0x01400000;
    


  • Ohne es ausprobiert zu haben: Ich meine, es müsste funktionieren. Da jeder Task seinen eigenen Adressraum bekommt, kann der Code auch jedesmal an dieselbe virtuelle Adresse geladen werden.

    edit: Und die virtuelle Adresse im Linkerscript sollte immer 0x01400000 sein, also auch hier keine Änderungen!



  • Wir hatten im IRC schon diskutiert, ob die Startadresse ein festert Wert sein muss oder ob man den Wert nur in einem bestimmten Breich einschränken muss. Gewisse Bereiche wird man ja im virtuellen Addressraum auch reserviert halten müssen für den Kernel oder Bibliotheken, aber da bleibt immer noch genügend Spielraum.

    Mir ging es nämlich darum das man bei beim schreiben von Anwendungen selten auf Linkerscripte zurückgreift. Der gcc soll wohl einen Standardwert für die Startadresse haben, aber was ist wenn ein anderer Compiler andere Standardwerte hat? Im User Mode sollte die Beschränkungen auf bestimmte Programmiersprachen/Compiler/Tools nicht mehr so stark sein.



  • gcc hat damit nichts zu tun, das ist ld. Und der benutzt sehr wohl ein Linkerskript, nur eben das Standardlinkerskript. Falls du irgendwann binutils auf deinem OS haben wirst, wirst du wohl auch dieses Standardlinkerskript anpassen - und damit letztendlich die Startadresse festlegen.


  • Mod

    In den cross-tools findet man dieses cygmon.ld:

    ...
    


  • Erhard Henkes schrieb:

    In den cross-tools findet man dieses cygmon.ld:

    ...
    

    Das Default-Linkerskript bekommst du übrigen mit ld --verbose heraus. Und das ist beim Cross-Compiler aus dem Lowlevel Wiki i586-elf\lib\ldscripts\elf_i386.xc.

    cygmon.ld ist Bestandteil von newlib. newlib ist nur mit weiteren Anpassungen zu verwenden. cygmon ist eine andere Geschichte.

    Wenn du dir einen Cross Compiler selbst erstellst, hast du mehr Kontrolle über diese Details.


  • Mod

    Danke für den Hinweis.

    in crosstools\i586-elf\lib\ldscripts\elf_i386.x findet man:

    /* Default linker script, for normal executables */
    OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
    OUTPUT_ARCH(i386)
    ENTRY(_start)
    SEARCH_DIR("/crosstools/i586-elf/lib");
    SECTIONS
    {
      /* Read-only sections, merged into text segment: */
      PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS;
    ...
    

    das ist beim Cross-Compiler aus dem Lowlevel Wiki i586-elf\lib\ldscripts\elf_i386.xc

    /* Script for -pie -z combreloc: position independent executable, combine & sort relocs */
    ...
    }
    

    Wir verwenden momentan dieses Linker-Script für User-Programme, bisher nur die shell, in PrettyOS:

    ENTRY(_start)
    OUTPUT_FORMAT(elf32-i386)
    SECTIONS
    {
        . = 0x1400000;
        .text   : { __code_start = .;   *(.text*)         }
        .data   : { __data_start = .;   *(.data)          }    
        .rodata : { __rodata_start = .; *(.rodata)        }
        .bss    : { __bss_start = .;    *(.bss) *(COMMON) }
         __end = .; 	
    }
    


  • Also sehe ich das richtig, bei dem Crosscompiler ist die default Base Address etwa bei 128 MB? Mag das mal jemand unter "richtigen" Linuxen testen?
    Wäre interessant im Hinblick darauf, in Zukunft evtl Linux-binaries ausführen zu können.



  • Hab zurzeit nur ein 64 Bit Linux am laufen. Aber wenn ich da mit -m32 kompiliere und mir mit readelf den Header zeigen lasse steht da Entry Point: 0x8048330. Das dürfte wohl auch 0x08048000 + Header entsprechen.

    Bei 64 Bit ist es übrigens 0x400000 (genau 4 MB).


  • Mod

    Damit unter Linux erfolgreich kompiliert werden konnte, mussten die ASSERTS auskommentiert werden.



  • Erhard Henkes schrieb:

    Damit unter Linux erfolgreich kompiliert werden konnte, mussten die ASSERTS auskommentiert werden.

    Man sollte dazu sagen das es wohl daran liegt das man keinen Crosscompiler benutzt. Es wird ein zweiter program header angelegt mit dem Namen "GNU_STACK" angelegt. Ich weiß nicht genau wofür der ist, aber man kann den wohl getrost ignorieren. Die Anzahl der Header ist halt nur nicht mehr 1 sondern 2.


  • Mod

    Damit könnte man über die Anzahl der Header die beiden Ergebniszustände diskriminieren.


Anmelden zum Antworten