Autor Thema: Stack wird verändert....  (Gelesen 5164 mal)

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« am: 19. July 2010, 18:02 »
Hallo,

ich habe ein Problem mit meinem Stack.

Folgende Funktion verändert den Stack:
int kmesg_putc(char c)
{
#if defined(CONFIG_SERIAL_KMESG)
error_p errno;
#endif /* CONFIG_SERIAL_KMESG */

kmesg_buf[kmesg_pointer++] = c;
#if defined(CONFIG_CONSOLE_KMESG)
con_put_char(c);
#endif /* CONFIG_CONSOLE_KMESG */
#if defined(CONFIG_SERIAL_KMESG)
rs232_send(0 , c , errno);
#endif /* CONFIG_SERIAL_KMESG */

return 1;
}
Der Befehl, der den Stack schmeißt, ist komischer Weise "return 1;".

Vor dem Befehl sieht der Stack wie folgt aus:
#0  kmesg_putc (c=91 '[') at lib/kprintf/kmesg.c:290
#1  0x0010280f in kaprintf (msg=0x102fde "PANIC] ", args=0x1070c8 "\370p\020")
    at lib/kprintf/kmesg.c:484
#2  0x00102855 in kprintf (msg=0x102fdd "[PANIC] ") at lib/kprintf/kmesg.c:504
#3  0x00102977 in panic (
    msg=0x102e30 "multiboot-magic-code is incorrect (expected: %#x , read: %#x)") at lib/kprintf/kmesg.c:559
#4  0x0010044f in init (mb_magic=38144, mb_struct=0xf000ff53) at init/init.c:69
ESP hat den Wert: 0x107024

Nach dem Aufruf sieht der Stack so aus:
#0  kmesg_putn (value=0) at lib/kprintf/kmesg.c:299
#1  0x00000000 in ?? ()
ESP hat den Wert: 0x107024

Woran kann das liegen?

Danke.

Gruß,
rizor

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

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 19. July 2010, 22:20 »
Was mir noch einfällt...
Der GDB gibt bei Funktionsprüngen ja immer den Funktionskopf mit Parametern an.
Das was an Parametern da steht ist meistens falsch.
Das wird erst nach dem ersten Befehl ordentlich gesetzt.

Keine Ahnung, ob das auch mit dem Fehler zusammen hängt
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

MNemo

  • Beiträge: 547
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 20. July 2010, 18:15 »
Ich weiß zwar nicht was genau dein Problem ist, aber das ein return den Stack verändert ist völlig normal. Es wird schließlich die Rücksprungadresse vom Stack geholt.
Mit deinem Stackbacktrace kann ich leider nicht viel anfangen, so 'nen luxus bin ich nicht gewohnt.  :-D
Aber das du das ganze mit GDB debuggst ist schon mal eine nützliche Information. Hast du daran gedacht die Compiler-Optimierung(-Ox) wegzulassen. Mit Optimierung ist  GDB nämlich nicht gerade gut zum Debuggen geeignet, weil der Binär- vom Quellcode meist erheblich abweicht.

Was ist denn genau dein Problem? Wenn du in C programmierst sollte es dich ja nicht stören was dein Compiler mit dem Stack anstellt, solang er selbst damit zurecht kommt.
„Wichtig ist nicht, besser zu sein als alle anderen. Wichtig ist, besser zu sein als du gestern warst!“

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 20. July 2010, 19:28 »
Das return den Stack verändert ist mir klar ;).
Allerdings dürfte er ihn nur um4 byte ikrementieren und nicht die Adresse so lassen und dafür den ganzen Stack verändern.
Der obere backtrace zeigt mir meinen Stack vor dem Return.
Nach der Return-Asuführung springt er in kmesg_putn und backtrace gibt mir danach den unteren Stack aus.
Die Flags habe ich alle weggelassen (arbeite mit -O0 -g).
An sich sollte der Compiler mit dem Stack klar kommen, sieht aber sehr komisch aus,wie der Stack nach dem Return aussieht.
Er dürfte ja nicht einmal in die kmesg_putn-Methode springen.
Was sehr komisch ist, ist dass er wirklich genau an den Anfang der Funktion springt, als wenn die Adresse auf dem Stack liegt.
« Letzte Änderung: 20. July 2010, 19:31 von rizor »
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 20. July 2010, 19:54 »
Allerdings dürfte er ihn nur um4 byte ikrementieren und nicht die Adresse so lassen und dafür den ganzen Stack verändern.

Es kann auch sein, dass GDB sich irrt. Vielleicht ist der Stack vom Aufbau nicht so, wie GDB ihn erwartet. Wenn der Kernel gestartet wird, ist ja auf dem Stack nichts sinnvolles, und in ebp hat auch keinen sinnvollen Wert. Ich müsste auch erstmal googeln, wie man einen korrekten Stackframe aufbaut, um C-Funktionen aufzurufen, aber ich glaube das geht ungefähr so:

_start:            ; <-- einsprungspunkt vom bootloader
    ; ...

    mov esp, ...   ; <-- esp auf kernelstack setzen

    push dword 0   ; rücksprung adresse (evtl. überflüssig?)
    mov ebp, 0
    push ebp       ; alter framepointer
    mov ebp, esp   ; esp nach ebp kopieren

    ; ...

    call ...       ; <--- C-Funktion aufrufen

Natürlich kann es trotzdem sein, dass das nichts bringt, weil das Problem woanders liegt.
« Letzte Änderung: 20. July 2010, 19:57 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 24. July 2010, 23:47 »
Habe mir den Stack mal genau angeschaut und der sollte stimmen.
Habe herausgefunden, dass der Fehler ab einer bestimmten Menge von Unterfunktionsaufrufen stattfindet (5. Aufruf).
Allerdings fliegt er nur, bei kprintf-Aufrufen.
Es liegt aber nicht an der Stack-Größe, da ich bei einer Verdopplung des Stacks noch den gleichen Fehler erhalte.
Mir ist auch noch aufgefallen, dass der GDB nicht bei meiner ASM-Startmethode halten kann. Er stommt die Ausführung erst ab der ersten C-Funktion, obwohl er das Symbol für die ASM-Methode findet.

Die Fehler erschließen sich mir leider nicht.

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

 

Einloggen