Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Low-Level-Programmierung und Experimenteller Kernel; Ansprechpartner: Dirty Oerti
Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Dirty Oerti » So Okt 19, 2008 7:40 pm

Ok..ich hab's nun soweit, dass es funktioniert.
Dazu muss ich allerdings eine andere Funktion in der Datei auskommentieren (?!?).

Der Fehler liegt anscheinend immer im PageFaultHandler (es scheint nicht möglich, darauf zuzugreifen..)

Folgendes funktioniert:

Code: Alles auswählen

unsigned short count;

void NewDir(unsigned int* dest)
{
    //###Inhalt ist nicht wichtig.
}

/*unsigned int *NewPageDir()
{
 // (...) ###ZUR ÜBERSICHTLICHKEIT => gekürzt
    return NewDir;//Gibt physikalische Adresse zurück!
}*/

// (...) ###ANDERE FUNKTIONEN

void PageFault_handler(struct regs *r)
{
// ###etc....
Folgendes funktioniert nicht:

Code: Alles auswählen

unsigned short count;

void NewDir(unsigned int* dest)
{
    //###Inhalt ist nicht wichtig.
}


////////////////#############FUNKTION ist nun nicht mehr auskommentiert
unsigned int *NewPageDir()
{
 // (...) ###ZUR ÜBERSICHTLICHKEIT => gekürzt
    return NewDir;//Gibt physikalische Adresse zurück!
}

// (...) ###ANDERE FUNKTIONEN

void PageFault_handler(struct regs *r)
{
// ###etc....
Der Inhalt der Funktionen ist mit sehr großer Sicherheit nicht interessant, da ich selbst schon unnütze Funktionen dazwischen gesetzt habe.
Sobal eine Funktion mehr in die Datei kommt, funktioniert es nicht mehr (keine Warnung, nichts, aber die CPU bekommt einen Triple Fault und der Rechner startet neu).

Jetzt habe ich mir die Ausgabe des Linkers mal angesehen...

So sieht es aus, wenn keine Funktion mit drinnen ist, alles also einwandfrei funktioniert:

Code: Alles auswählen

(...)
 .text          0x000000000010279c       0xac mboot.o
                0x00000000001027c2                UseMultiBootInfo
                0x000000000010279c                ExtractInitRamDisk
 .text          0x0000000000102848      0x3d8 paging.o
                0x0000000000102968                PGoff_SetPageEntry
                0x000000000010288f                GetPTEntry
                0x00000000001029a7                PGoff_GetPageEntry
                0x00000000001029cb                IdentityMap_Dir
                0x0000000000102848                SetPTEntry
                0x0000000000102aae                Init_Paging
                0x00000000001028bb                NewDir
                0x000000000010293f                Switch_Page_Directory
                0x0000000000102b3b                PageFault_handler
 .text          0x0000000000102c20      0x51d phys-mm.o
(...)
Passiert ein Fehler (es ist also eine Funktion mehr in der Datei), dann sieht die Ausgabe wie folgt aus:

Code: Alles auswählen

(...)
 .text          0x000000000010279c       0xac mboot.o
                0x00000000001027c2                UseMultiBootInfo
                0x000000000010279c                ExtractInitRamDisk
 .text          0x0000000000102848      0x44a paging.o
                0x00000000001029da                PGoff_SetPageEntry
                0x000000000010288f                GetPTEntry
                0x0000000000102a19                PGoff_GetPageEntry
                0x0000000000102a3d                IdentityMap_Dir
                0x0000000000102848                SetPTEntry
                0x0000000000102b20                Init_Paging
                0x000000000010293f                NewPageDir    (ZUSÄTZLICHE FUNKTION)
                0x00000000001028bb                NewDir
                0x00000000001029b1                Switch_Page_Directory
                0x0000000000102bad                PageFault_handler
 *fill*         0x0000000000102c92        0x2 00     (SONSTIGE ÄNDERUNG)
 .text          0x0000000000102c94      0x51d phys-mm.o
(...)
Mir ist aufgefallen:
Es wird ein Bereich zusätzlich mit 0 gefüllt:

Code: Alles auswählen

 *fill*         0x0000000000102c92        0x2 00     (SONSTIGE ÄNDERUNG)
Könnte es dadrann liegen?


---------
fat-lobyte hat geschrieben:Vielleicht ist einer der Funktionen die zwischen einer Zeile über dem Fehler und dem Anfang des auskommentierten Codes ein Makro, dass entweder Fehler enthält oder das Makro wurde falsch verwendet.
Außerdem könnte es sein, dass eine dieser Funktionen oder eine Variable nicht deklariert ist, oder vielleicht fehlt irgendwo eine Klammer oder ein Semikolon.

Das wird dir nicht viel Weiterhelfen, aber das sind die möglichkeiten, wie so etwas passieren kann.
Ein Makro...muss ich mal nachgucken, aber das würde doch eigntl zumindest zu einem Linkerfehler führen, oder?
Ein Semikolon oder eine Klammer ist es nicht.
Das würde gcc ja bemerken. Ich habe höchste Warnstufe eingestellt, ich bekomme also jede noch so kleine Warnung.

Es hilft schonmal in dem Sinne, dass du dir Gedanken dazu gemacht hast.
Ich fühle mich nun nicht mehr so alleine :) ^^
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Dirty Oerti » So Okt 19, 2008 10:24 pm

Es scheint ganz wo anders zu liegen.
Der Instruction Pointer (laut Bochs Protokollausgabe) zeigt beim TripleFault auf
00026371977i[CPU0 ] | RIP=00000000001005fa (00000000001005fa)
Ich habe die Datei "basic-kernel.bin" nun mal mit objdump -d disassembliert, und die entsprechende Stelle gesucht:

Code: Alles auswählen

001005df <memset>:
  1005df:	55                   	push   %ebp
  1005e0:	89 e5                	mov    %esp,%ebp
  1005e2:	83 ec 14             	sub    $0x14,%esp
  1005e5:	8b 45 0c             	mov    0xc(%ebp),%eax
  1005e8:	88 45 ec             	mov    %al,-0x14(%ebp)
  1005eb:	8b 45 08             	mov    0x8(%ebp),%eax
  1005ee:	89 45 fc             	mov    %eax,-0x4(%ebp)
  1005f1:	eb 11                	jmp    100604 <memset+0x25>
  1005f3:	8b 55 fc             	mov    -0x4(%ebp),%edx
  1005f6:	0f b6 45 ec          	movzbl -0x14(%ebp),%eax
  1005fa:	88 02                	mov    %al,(%edx)   ###############HIER ist der FEHLER
  1005fc:	83 45 fc 01          	addl   $0x1,-0x4(%ebp)
  100600:	83 6d 10 01          	subl   $0x1,0x10(%ebp)
  100604:	83 7d 10 00          	cmpl   $0x0,0x10(%ebp)
  100608:	75 e9                	jne    1005f3 <memset+0x14>
  10060a:	8b 45 08             	mov    0x8(%ebp),%eax
  10060d:	c9                   	leave  
  10060e:	c3                   	ret    
Die Anweisung

Code: Alles auswählen

  1005fa:	88 02                	mov    %al,(%edx)
scheint das Problem zu sein.
Die Funktion sieht in C Code so aus:

Code: Alles auswählen

void *memset(void *dest, char val, unsigned long count)
{
        char *temp = (char *)dest;
        for( ; count != 0; count--) *temp++ = val;
        return dest;
}
Was könnte hier falsch laufen?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Kerli » So Okt 19, 2008 10:58 pm

Dirty Oerti hat geschrieben:Die Funktion sieht in C Code so aus:

Code: Alles auswählen

    void *memset(void *dest, char val, unsigned long count)
    {
            char *temp = (char *)dest;
            for( ; count != 0; count--) *temp++ = val;
            return dest;
    }
Ich habe bis jetzt nicht viel Erfahrungen mit Assembler gemacht. Aber mir sind an der Funktion zwei potentielle Fehlerquellen aufgefallen. Wenn du einen Zeiger auf einen Speicherbereich übergibst dessen Größe nicht in 'char' berechnet wurde, dann könnte etwas schiefgehen, und wenn 'count' ungültig ist könnte es auch zu sehr unschönen Zugriffsfehlern kommen.

Ansonsten kann ich dir leider glaub ich nicht viel weiterhelfen.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von fat-lobyte » So Okt 19, 2008 11:52 pm

Dirty Oerti hat geschrieben:Es scheint ganz wo anders zu liegen.
Der Instruction Pointer (laut Bochs Protokollausgabe) zeigt beim TripleFault auf
00026371977i[CPU0 ] | RIP=00000000001005fa (00000000001005fa)
Ich habe die Datei "basic-kernel.bin" nun mal mit objdump -d disassembliert, und die entsprechende Stelle gesucht: Die Anweisung

Code: Alles auswählen

  1005fa:	88 02                	mov    %al,(%edx)
scheint das Problem zu sein.


Was könnte hier falsch laufen?
Hm... So wies aussieht hast du eine ungewöhnliche Calling Convention: Nicht alle Parameter werden auf dem Stack übergeben, beispielsweise wird das edx Register nicht in dieser Funktion gesetzt. Ich nehme an, das ist ein Parameter, und zwar void* dest.
Des Bedeutet, die Zeile würde
char *temp = (char *)dest;
Entsprechen. Somit müsste der Fehler in der aufrufenden Funktion liegen.
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Dirty Oerti » Mo Okt 20, 2008 12:21 pm

fat-lobyte hat geschrieben:
Dirty Oerti hat geschrieben:Es scheint ganz wo anders zu liegen.
Der Instruction Pointer (laut Bochs Protokollausgabe) zeigt beim TripleFault auf
00026371977i[CPU0 ] | RIP=00000000001005fa (00000000001005fa)
Ich habe die Datei "basic-kernel.bin" nun mal mit objdump -d disassembliert, und die entsprechende Stelle gesucht: Die Anweisung

Code: Alles auswählen

  1005fa:	88 02                	mov    %al,(%edx)
scheint das Problem zu sein.


Was könnte hier falsch laufen?
Hm... So wies aussieht hast du eine ungewöhnliche Calling Convention: Nicht alle Parameter werden auf dem Stack übergeben, beispielsweise wird das edx Register nicht in dieser Funktion gesetzt. Ich nehme an, das ist ein Parameter, und zwar void* dest.
Des Bedeutet, die Zeile würde
char *temp = (char *)dest;
Entsprechen. Somit müsste der Fehler in der aufrufenden Funktion liegen.
Ich habe es gestern noch gelöst bekommen, hatte aber leider kein Internet mehr, um es euch mitzuteilen :)
Eure Vermutung mit den Parametern ist schon sehr richtig.

Es funktioniert alles einwandfrei, wenn die Funktion so aussieht:

Code: Alles auswählen

void *memset(void *dest, char val, unsigned short count)
{
        char *temp = (char *)dest;
        for( ; count != 0; count--) *temp++ = val;
        return dest;
}
Anscheinend funktioniert das nicht mit long Typen.... *trotzdem nicht verstehe, wie das mit der zusätzlichen Funktion zusammenhängt*
Das tolle daran: Die Funktion ist nun auch kleiner geworden, und damit auch schneller.

Könnte mir aber dennoch jemand versuchen zu erklären, warum das mit long nicht funktioniert?
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von fat-lobyte » Mo Okt 20, 2008 12:30 pm

Dirty Oerti hat geschrieben:Es funktioniert alles einwandfrei, wenn die Funktion so aussieht:

Code: Alles auswählen

void *memset(void *dest, char val, unsigned short count)
{
        char *temp = (char *)dest;
        for( ; count != 0; count--) *temp++ = val;
        return dest;
}
Anscheinend funktioniert das nicht mit long Typen.... *trotzdem nicht verstehe, wie das mit der zusätzlichen Funktion zusammenhängt*
Das tolle daran: Die Funktion ist nun auch kleiner geworden, und damit auch schneller.

Könnte mir aber dennoch jemand versuchen zu erklären, warum das mit long nicht funktioniert?
Seltsam...
Also das sollte keinen Unterschied machen. Was ich eigentlich gemeint habe war, dass der Fehler nicht in DIESER Funktion lag, sondern in der Funktion, die diese aufruft. So wie ich das sehe ist das ein glatter Buffer overflow, oder ein nicht initialisierter Zeiger. Poste bitte mal den Disassembly für die short version. Und nett wäre noch die Adresse des Symbols "memset", damit man die ganzen Sprünge identifizieren kann.
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Xin » Mo Okt 20, 2008 12:31 pm

Dirty Oerti hat geschrieben:Es funktioniert alles einwandfrei, wenn die Funktion so aussieht:

Code: Alles auswählen

void *memset(void *dest, char val, unsigned short count)
{
        char *temp = (char *)dest;
        for( ; count != 0; count--) *temp++ = val;
        return dest;
}
Anscheinend funktioniert das nicht mit long Typen.... *trotzdem nicht verstehe, wie das mit der zusätzlichen Funktion zusammenhängt*
Wenn Du es nicht verstehst, ist es falsch.

Ändere die Funktion wieder nach unsigned long und finde den Fehler, die Funktionen muss identisch sein.
Dirty Oerti hat geschrieben:Das tolle daran: Die Funktion ist nun auch kleiner geworden, und damit auch schneller.
Wegen long => short kleiner geworden?!?
Dirty Oerti hat geschrieben:Könnte mir aber dennoch jemand versuchen zu erklären, warum das mit long nicht funktioniert?
Du hast einen Fehler im Programm oder - sehr unwahrscheinlich - einen Fehler im Compiler gefunden.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Dirty Oerti » Mo Okt 20, 2008 1:11 pm

Ok...hier kommt die gewünscht Info:

Zuerst:

Mit Long

Code: Alles auswählen

001005ef <memset>:
  1005ef:	55                   	push   %ebp
  1005f0:	89 e5                	mov    %esp,%ebp
  1005f2:	83 ec 14             	sub    $0x14,%esp
  1005f5:	8b 45 0c             	mov    0xc(%ebp),%eax
  1005f8:	88 45 ec             	mov    %al,-0x14(%ebp)
  1005fb:	8b 45 08             	mov    0x8(%ebp),%eax
  1005fe:	89 45 fc             	mov    %eax,-0x4(%ebp)
  100601:	eb 11                	jmp    100614 <memset+0x25>
  100603:	8b 55 fc             	mov    -0x4(%ebp),%edx
  100606:	0f b6 45 ec          	movzbl -0x14(%ebp),%eax
  10060a:	88 02                	mov    %al,(%edx)
  10060c:	83 45 fc 01          	addl   $0x1,-0x4(%ebp)
  100610:	83 6d 10 01          	subl   $0x1,0x10(%ebp)
  100614:	83 7d 10 00          	cmpl   $0x0,0x10(%ebp)
  100618:	75 e9                	jne    100603 <memset+0x14>
  10061a:	8b 45 08             	mov    0x8(%ebp),%eax
  10061d:	c9                   	leave  
  10061e:	c3                   	ret    
C-Code dazu:

Code: Alles auswählen

void *memset(void *dest, char val, unsigned long count)
{
        char *temp = (char *)dest;
        for( ; count != 0; count--) *temp++ = val;
        return dest;
}
Mit Short:

Code: Alles auswählen

001005ef <memset>:
  1005ef:	55                   	push   %ebp
  1005f0:	89 e5                	mov    %esp,%ebp
  1005f2:	83 ec 18             	sub    $0x18,%esp
  1005f5:	8b 45 0c             	mov    0xc(%ebp),%eax
  1005f8:	8b 55 10             	mov    0x10(%ebp),%edx
  1005fb:	88 45 ec             	mov    %al,-0x14(%ebp)
  1005fe:	66 89 55 e8          	mov    %dx,-0x18(%ebp)
  100602:	8b 45 08             	mov    0x8(%ebp),%eax
  100605:	89 45 fc             	mov    %eax,-0x4(%ebp)
  100608:	eb 12                	jmp    10061c <memset+0x2d>
  10060a:	8b 55 fc             	mov    -0x4(%ebp),%edx
  10060d:	0f b6 45 ec          	movzbl -0x14(%ebp),%eax
  100611:	88 02                	mov    %al,(%edx)
  100613:	83 45 fc 01          	addl   $0x1,-0x4(%ebp)
  100617:	66 83 6d e8 01       	subw   $0x1,-0x18(%ebp)
  10061c:	66 83 7d e8 00       	cmpw   $0x0,-0x18(%ebp)
  100621:	75 e7                	jne    10060a <memset+0x1b>
  100623:	8b 45 08             	mov    0x8(%ebp),%eax
  100626:	c9                   	leave  
  100627:	c3                   	ret    
c-Code:

Code: Alles auswählen

void *memset(void *dest, char val, unsigned short count)
{
        char *temp = (char *)dest;
        for( ; count != 0; count--) *temp++ = val;
        return dest;
}

Ok...äh..nun scheint die (nicht funktionierende) Version mit long kürzer zu sein..

Zum Aufruf der Funktion:
Der Aufruf erfolgt immer gleich, an dem Part, an dem es abbricht sieht der Aufruf so aus:

Code: Alles auswählen

memset(OList.List, 0, max_size*sizeof(type_t));
OList.List ist ein gültiger Zeiger, 0 ist der Wert, mit dem der Speicher gefüllt werden soll, max_size ist positiv, sizeof(type_t) ist 4.
Nirgends wird ein Wert irgendwie zu groß oder negativ...
(Sind recht statische Werte)
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Dirty Oerti » Sa Okt 25, 2008 12:51 pm

Habe wieder ein Problem an der selben Stelle (bzw im selben Bereich).

Das alles scheint mehr mit Paging zusammenzuhängen, dass dann irgendwie etwas nicht gelesen werden kann.

Habe jetzt eine Funktion eingebaut, um Directories zu klonen.
Die Funktioniert auch super.
Problem ist nur:
Mit dieser Funktion und memset_4byte mit int/long kommt wieder eine "Exception with no resolution".
Ist der Parameter von memset_4byte allerdings "short", dann "funktioniert" es.
Und ich habe keine Ahnung zu den Zusammenhängen...

*edit*
Nicht das ihr denkt, ich wäre untätig gewesen:
ich arbeite daran, dass mein Multitasking richtig funktioniert.
Task Switch funktionieren, aber ich kann keinen neuen Task erstellen (sinnvoll^^).

*/edit*

EDIT:
Um dabei nicht stehen zu bleiben, lasse ich jetzt den Parameter vorerst auf "short". Damit "funktioniert" es vorerst.
Mein Problem liegt eben hauptsächlich darin, dass ich nicht verstehe, warum das so ist etc.
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Benutzeravatar
Dirty Oerti
Beiträge: 2229
Registriert: Di Jul 08, 2008 5:05 pm
Wohnort: Thurndorf / Würzburg

Re: Aktuelle Bugs: Wer ihn findet, darf ihn behalten!

Beitrag von Dirty Oerti » Di Okt 28, 2008 5:10 pm

Ok, Parameter stehen auf short, aber es funktioniert nun trotzdem nicht richtig.
Und zwar wieder, wenn ich eine Funktion mehr einbaue.

Habe leider keine Ahnung, woran das liegt :(
*grr*

Werde mal testen, ob es evtl nur an bochs liegt...
Bei Fragen einfach an daniel[ät]proggen[Punkt]org
Ich helfe gerne! :)
----------
Wenn du ein Licht am Ende des Tunnels siehst, freu dich nicht zu früh! Es könnte ein Zug sein, der auf dich zukommt!
----
It said: "Install Win95 or better ..." So I installed Linux.

Antworten