Lowlevel

Lowlevel => Softwareentwicklung => Thema gestartet von: OsDevNewbie am 08. August 2013, 21:27

Titel: Problem mit externen Variablen (vom Linker erstellt)
Beitrag von: OsDevNewbie am 08. August 2013, 21:27
Hallo,
ich bin gerade dabei cdi_init() zu programmieren und bin auf folgendes Problem gestossen: Ich habe mir in Tyndur angeschaut, wie sie das so machen. Ich habe dort einige Teile übernommen nachdem ich verstanden habe, was diese machen. Nun bekomme ich aber zwei Fehlermeldungen vom Compiler:
undefined reference to `__start_cdi_drivers'
undefined reference to `__stop_cdi_drivers'
Die entsprechende Datei ist (cdi.c, nur der wichtigste Teil):
#include "cdi.h"

extern struct cdi_driver *__start_cdi_drivers;
extern struct cdi_driver *__stop_cdi_drivers;

cdi_list_t drivers;

void cdi_init()
{
struct cdi_driver **pdrv;
struct cdi_driver *drv;

drivers = cdi_list_create();

// Alle in dieser Binary verfuegbaren Treiber aufsammeln
for(pdrv = &__start_cdi_drivers; pdrv < &__stop_cdi_drivers; pdrv++)
{
drv = *pdrv;
if(drv->init != NULL)
{
drv->init();
cdi_driver_register(drv);
}
}
}
Ich habe schon alles versucht, bekomme aber den Fehler nicht weg. Ich habe auch schon mal diese zwei Variablen im Linkerscript definiert, hat aber nichts gebracht. Ich habe das so verstanden, dass diese zwei Werte vom Linker definiert werden oder nicht?

Hier noch das Linkerscript:
OUTPUT_FORMAT(elf64-x86-64)
OUTPUT_ARCH(i386:x86-64)
/*  Bei _start soll die Ausfuehrung losgehen */
ENTRY(_start)

/*
 * Hier wird festgelegt, in welcher Reihenfolge welche Sektionen in die Binary
 * geschrieben werden sollen
 */
SECTIONS
{
    /*
     * . ist die aktuelle Position in der Datei. Wir wollen den Kernel wie gehabt
     * an 1 MB laden, also muessen wir dort die erste Sektion hinlegen
     */
    . = 0x100000;
kernel_start = .;

    /*
     * Der Multiboot-Header muss zuerst kommen (in den ersten 8 kB).
     * Die Standardsektionen einfach hintereinander weg einbinden.
     */
    .text : {
        /*(multiboot) kein Multibootheader vorhanden.*/
        *(.text)
    }
    .data ALIGN(4096) : {
        *(.data)
    }
    cdi_drivers ALIGN(4096) : {
        *(cdi_drivers)
    }
    .rodata ALIGN(4096) : {
        *(.rodata)
    }
    .bss ALIGN(4096) : {
        *(.bss)
    }
kernel_end = .;
}

Ich hoffe ihr könnt mir helfen.
Titel: Re: Problem mit externen Variablen (vom Linker erstellt)
Beitrag von: kevin am 09. August 2013, 08:48
Wie sieht deine Deklaration von CDI_DRIVER() aus? Legst du dort die Variablen in der Section cdi_drivers an?
Titel: Re: Problem mit externen Variablen (vom Linker erstellt)
Beitrag von: OsDevNewbie am 09. August 2013, 16:21
Die Definition von CDI_DRIVER() habe ich einfach aus Tyndur übernommen.
#define cdi_glue(x, y) x ## y
#define cdi_declare_driver(drv, counter) \
    static const void* __attribute__((section("cdi_drivers"), used)) \
        cdi_glue(__cdi_driver_, counter) = &drv;

#define CDI_DRIVER(name, drv, deps...) cdi_declare_driver(drv, __COUNTER__)
Titel: Re: Problem mit externen Variablen (vom Linker erstellt)
Beitrag von: kevin am 09. August 2013, 17:19
Also tyndur hat cdi_drivers überhaupt nicht im Linkerskript stehen. Das könnte eine Voraussetzung dafür sein, dass __start/stop_* überhaupt generiert werden, siehe http://sourceware.org/binutils/docs/ld/Orphan-Sections.html (da steht zwar nicht, dass das sonst nicht passiert, aber eben, dass es bei solchen Sections passiert)
Titel: Re: Problem mit externen Variablen (vom Linker erstellt)
Beitrag von: OsDevNewbie am 09. August 2013, 17:38
Danke vielmals für deine Hilfe.
Also gibt es zwei Möglichkeiten: