Forum: Compiler & IDEs Initialisiertes Char Feld mit Länge 1 und Inhalt '\0'?


von Holm T. (Gast)


Lesenswert?

Ich habe mich jetzt mal mit der vergriesgnaddelten Ausgabe des md 
Kommandos  aus dem Thread  hier

Beitrag "bare metal m68k-elf.gcc."

befaßt:
1
MOTOROLA> md 2000
2
��(�w�����$00002000:  $0005  $4445  $0041  $4410  $0940  $0444

...es gibt da eine Funktion getcount() in general.c:
1
getcount(str,size,strt,err)
2
char *str;      /* string with <range> on it */
3
int size;       /* 1,2 or 4; the number of bytes from <size> */
4
int strt;       /* starting address */
5
char err[];     /* error message to print if in error */
6
...

..die beim Aufruf unter Anderem verschiedene Fehlermeldungen mitgegeben 
bekommt, die sie im Fehlerfalle ausgeben soll. Diese Fehlermeldungen 
werden in textdef.h wie folgt vereinbahrt:
1
char NOERR[] = "";
2
char ERR01[] = "ERROR 01: illegal number of arguments\n";
3
char ERR02[] = "ERROR 02: illegal address syntax\n";
4
char ERR03[] = "ERROR 03: illegal number syntax\n";
5
char ERR04[] = "ERROR 04: illegal option\n";
6
char ERR05[] = "ERROR 05: insufficient room to insert data\n";
7
char ERR06[] = "ERROR 06: breakpoint table is full\n";
8
char ERR07[] = "ERROR 07: illegal command call\n";
9
char ERR08[] = "\nERROR 08: S-record load failed, invalid checksum = ";
10
char ERR09[] = "ERROR 09: invalid assembly => ";

ich habe mir die Pointer zu den Strings ausgeben lassen, das ist hier 
(ohne virtual memory) direkt die physisch Speicheradresse des Feldes im 
ROM. Im ROM deshalb, weil der Linker .text und .data im ROM ablegt, .bss 
liegt im RAM.

Das Linker Mapfile zeigt mir aber Folgendes:
1
.data           0x000000000080c200      0xfc8
2
 *(.data .data.* .gnu.linkonce.d.*)
3
 .data          0x000000000080c200        0x0 asmstartport.o
4
 .data          0x000000000080c200        0x0 asmhandler.o
5
 .data          0x000000000080c200      0xf74 coldport.o
6
                0x000000000080c200                equality
7
                0x000000000080c23c                f
8
                0x000000000080c338                p
9
                0x000000000080c35c                syn
10
                0x000000000080c3b0                ERR09
11
                0x000000000080c3cf                ERR08
12
                0x000000000080c404                ERR07
13
                0x000000000080c424                ERR06
14
                0x000000000080c448                ERR05
15
                0x000000000080c474                ERR04
16
                0x000000000080c48e                ERR03
17
                0x000000000080c4af                ERR02
18
                0x000000000080c4d1                ERR01
19
                0x000000000080c4f8                MMASHELPMSG

huh? "NOERR" fehlt ...

Hier ist es:
1
bss            0x00000000001fe000      0xa2c
2
 *(.dynbss)
3
 *(.bss .bss.* .gnu.linkonce.b.*)
4
 .bss           0x00000000001fe000        0x0 asmstartport.o
5
 .bss           0x00000000001fe000        0x0 asmhandler.o
6
 .bss           0x00000000001fe000        0x1 coldport.o
7
                0x00000000001fe000                NOERR
8
 *fill*         0x00000000001fe001        0x3 00

Wieso liegt das im RAM? Es sieht so aus, das der Compiler das Feld NOERR 
direkt an den Anfang das .bss segmentes mappt...seltsam.
Ich hatte gedacht (und Motorola wohl auch) das die Initalisierung des 1. 
Elementes mit einer 0x0 ('\0') bewerkstelligt wird, als String mit der 
Länge 0 aber mit Ende Kennung. Offensichtlich ergibt das aber ein Feld 
von Charactern mit 0 Elementen Länge? Wie ich herausbekommen habe, 
ändert die Deklaration als:
1
char NOERR[] = {0};
 daran überhaupt Nichts. Schreibe ich aber
1
char NOERR[] = {0x30};
...schwupps ist das Scheißding im .data Segment und auch initalisiert?
1
                0x000000000080c35c                syn
2
                0x000000000080c3b0                ERR09
3
                0x000000000080c3cf                ERR08
4
                0x000000000080c404                ERR07
5
                0x000000000080c424                ERR06
6
                0x000000000080c448                ERR05
7
                0x000000000080c474                ERR04
8
                0x000000000080c48e                ERR03
9
                0x000000000080c4af                ERR02
10
                0x000000000080c4d1                ERR01
11
                0x000000000080c4f8                NOERR
12
                0x000000000080c4f9                MMASHELPMSG

Ein volatile char NOERR[] = {0}; tut auch nicht, woher kriege ich ohne 
Kopfstände einen leeren String, oder anders ein Character Feld mit der 
Länge 1 und dem Inhalt 0? Di Deklaration sollte dann auch zu den 
restlichen Char Feldern passen und keine Extrabehandlung erfordern...

Der gcc wie nebenan empfohlen:

$ m68k-elf-gcc -v
Using built-in specs.
COLLECT_GCC=m68k-elf-gcc
COLLECT_LTO_WRAPPER=/usr/home/holm/cross/m68k/libexec/gcc/m68k-elf/4.6.2 
/lto-wrapper
Target: m68k-elf
Configured with: ../configure --target=m68k-elf 
--prefix=/usr/home/holm/cross/m68k --enable-languages=c --with-newlib 
--disable-libmudflap --disable-libssp --disable-libgomp 
--disable-libstdcxx-pch --disable-threads --with-gnu-as --with-gnu-ld 
--disable-nls --with-headers=yes --disable-checking --without-headers 
--with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local
Thread model: single
gcc version 4.6.2 (GCC)

Optimierung ist -Os -fomit-frame-pointer

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Probier' mal mit -fno-merge-constants, ob das was ändert.

von Holm T. (Gast)


Lesenswert?

Es geht mit const char NOERR[]="";

Deinen Tip probiere ich morgen aus...


Danke,

Holm

von Stefan E. (sternst)


Lesenswert?

1) .data liegt im RAM. Im ROM liegen die Initialisierungsdaten dafür.

2) In .bss liegt das, was keine speziellen Initialisierungsdaten 
benötigt, weil mit 0 initialisiert.

3) Deine Annahme bezüglich "Länge ist 0" ist falsch.

Ergo: alles ist in bester Ordnung.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Holm Tiffe schrieb:
> woher kriege ich ohne Kopfstände einen leeren String, oder anders ein
> Character Feld mit der Länge 1 und dem Inhalt 0?

Irgendein Zeiger, der auf ein Byte zeigt, welches 0 ist, erfüllt
diese Bedingung: was anderes ist ein leerer String ja nicht.

Herzlichen Glückwunsch übrigens noch. ;-)

von Holm T. (Gast)


Lesenswert?

Stefan Ernst schrieb:
> 1) .data liegt im RAM. Im ROM liegen die Initialisierungsdaten dafür.

Hier liegst Du leider völlig falsch mein Guter, .data liegt exakt dort, 
wo ich es hin definiert habe und dieser Bereich ist bei mir im ROM.


>
> 3) Deine Annahme bezüglich "Länge ist 0" ist falsch.
>
> Ergo: alles ist in bester Ordnung.

Ach? Dann liegt wohl NOERR auch da wo es hin gehört und der Rest ist ein 
Fatamorgana weil die Luft über dem 68010 so flimmert?

Der Memory-Dump Code ging schief weil die Pointer auf ein Feld das 0x0 
enthalten sollte mit dem Sauerkraut gefüllt war das ein nicht 
initialisiertes statisches RAM so an sich hat, konkret 0x8a.

Du hast sicher nicht realisiert das ich nicht unter den Bedingungen 
eines OS hantiere, sondern auf der blanken Hardware, hier konkret im 
Monitor.
Bei diesem liegen .text und .data im ROM, der Rest in .bss und damit im 
RAM.

Der Compiler hat das Symbol sicherlich nach .bss geschleppt und 
vorgesehen es im crt0.o irgendwo zu initialisieren, nur den Code der das 
macht gibts hier gar nicht weil crt0.o nicht mit dazu gelinkt ist.

Gruß,

Holm

von Holm T. (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Holm Tiffe schrieb:
>> woher kriege ich ohne Kopfstände einen leeren String, oder anders ein
>> Character Feld mit der Länge 1 und dem Inhalt 0?
>
> Irgendein Zeiger, der auf ein Byte zeigt, welches 0 ist, erfüllt
> diese Bedingung: was anderes ist ein leerer String ja nicht.


Ich weiß J, genau so einen Zeiger will das Konstrukt ja eigentlich 
anlegen.

Ich finde es halt nur seltsam, dass der Ort an dem eine Variable 
angelegt wird von dessen initialisiertem Inhalt abhängig zu sein 
scheint.
Ein "const" vor der Felddefinition macht dem Spuk ein Ende, die Strings 
sind eh Konstante.

> Herzlichen Glückwunsch übrigens noch. ;-)

Nach 14 Jahren Testbetrieb keine Ursache zur Aufregung.
Sorry, ich hatte versucht den Impact der Veranstalltung so klein wie 
möglich zu halten was mit aber nicht ganz gelungen ist.
Du hast es aber eh gewußt :-)

Wir telenieren nochmal darüber..


Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Holm Tiffe schrieb:
> Jörg Wunsch schrieb:
>> Holm Tiffe schrieb:
>>> woher kriege ich ohne Kopfstände einen leeren String, oder anders ein
>>> Character Feld mit der Länge 1 und dem Inhalt 0?
>>
>> Irgendein Zeiger, der auf ein Byte zeigt, welches 0 ist, erfüllt
>> diese Bedingung: was anderes ist ein leerer String ja nicht.
>

Drum der Vorschlag mit -fno-merge-constants. -Os impliziert 
-fmerge-constants, d.h. der Linker versucht, wertmäßig identische 
Konstanten zusammenzulegen.

Wär' das der Grund, hätte er einfach das erstbeste Nullbyte verzeigert, 
das er gefunden hat - bloß daß das keins ist/bleibt.

Das hieße aber bloß, daß dein Fehler woanders ist: möglicherweise (;)) 
geht gcc davon aus, daß dein Startup-Code das .bss Segment initialisiert 
und Du hast das vergessen... ?

von Stefan E. (sternst)


Lesenswert?

Holm Tiffe schrieb:
> Stefan Ernst schrieb:
>> 1) .data liegt im RAM. Im ROM liegen die Initialisierungsdaten dafür.
>
> Hier liegst Du leider völlig falsch mein Guter, .data liegt exakt dort,
> wo ich es hin definiert habe und dieser Bereich ist bei mir im ROM.

Ich kann ja nicht ahnen, dass du dir was eigenes zusammengestellt hast, 
was jenseits des Üblichen ist.

>> 3) Deine Annahme bezüglich "Länge ist 0" ist falsch.
>>
>> Ergo: alles ist in bester Ordnung.
>
> Ach? Dann liegt wohl NOERR auch da wo es hin gehört

Ja, eigentlich schon.
Wenn du dir natürlich eigene Definitionen festlegst, wo was hingehört, 
dann vielleicht nicht. Aber das kann der Compiler ja nicht wissen.

von Holm T. (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Holm Tiffe schrieb:
>> Stefan Ernst schrieb:
>>> 1) .data liegt im RAM. Im ROM liegen die Initialisierungsdaten dafür.
>>
>> Hier liegst Du leider völlig falsch mein Guter, .data liegt exakt dort,
>> wo ich es hin definiert habe und dieser Bereich ist bei mir im ROM.
>
> Ich kann ja nicht ahnen, dass du dir was eigenes zusammengestellt hast,
> was jenseits des Üblichen ist.


Doch, das konntest Du. Du hättest einfach nur den Thread oder den 
vorhergehenden lesen müssen :-)

>
>>> 3) Deine Annahme bezüglich "Länge ist 0" ist falsch.
>>>
>>> Ergo: alles ist in bester Ordnung.
>>
>> Ach? Dann liegt wohl NOERR auch da wo es hin gehört
>
> Ja, eigentlich schon.
> Wenn du dir natürlich eigene Definitionen festlegst, wo was hingehört,
> dann vielleicht nicht. Aber das kann der Compiler ja nicht wissen.

Das weiß im Endeffekt nur der Lader und der durch das Linkerscript bzw. 
die dazugehörigen Variablen auf seiner Kommandozeile.

Gruß,

Holm

von Holm T. (Gast)


Lesenswert?

Markus F. schrieb:
> Holm Tiffe schrieb:
>> Jörg Wunsch schrieb:
>>> Holm Tiffe schrieb:
>>>> woher kriege ich ohne Kopfstände einen leeren String, oder anders ein
>>>> Character Feld mit der Länge 1 und dem Inhalt 0?
>>>
>>> Irgendein Zeiger, der auf ein Byte zeigt, welches 0 ist, erfüllt
>>> diese Bedingung: was anderes ist ein leerer String ja nicht.
>>
>
> Drum der Vorschlag mit -fno-merge-constants. -Os impliziert
> -fmerge-constants, d.h. der Linker versucht, wertmäßig identische
> Konstanten zusammenzulegen.
>
> Wär' das der Grund, hätte er einfach das erstbeste Nullbyte verzeigert,
> das er gefunden hat - bloß daß das keins ist/bleibt.
>
> Das hieße aber bloß, daß dein Fehler woanders ist: möglicherweise (;))
> geht gcc davon aus, daß dein Startup-Code das .bss Segment initialisiert
> und Du hast das vergessen... ?

Ja, ich probiere das noch aus.

Der fbug initialisiert den von ihm genutzen RAM schon selber 
(coldport.c)
und gcc überläßt die Initialisierung einer Routine in der Bibliothek 
(crt0.o). Im konkreten Einsatzfalle wäre ein Löschen des RAMs eher 
kontraproduktiv, weshalb es auch unterbleibt.

Ich habe das also nicht vergessen, sondern "Jemand" (mit an dieser 
Stelle beschränkter Einsicht) hat vorausgesetzt das das immer so ist.

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Da gibt's übrigens noch ein kleines, aber feines Detail:
1
char string[] = "Stringliteral";
ist tatsächlich keins. Der Compiler muß das Feld im RAM anlegen, weil es 
eine Initialisierung eines nichtkonstanten Feldes ist.
1
char *string = "Stringliteral";
ist wirklich eins. Das darf im readonly-Memory bleiben und wäre wohl in 
deinem konkreten Fall die einfachste (und richtige) Lösung.

von Holm T. (Gast)


Lesenswert?

Dann hätte der Compiler mal die und mal die Ansicht über das was ich 
machen will:
Er versucht ja NOERR als einen Pointer auf 0 anzulegen indem er es an 
den Anfang des .bss Segmentes legt, unter der Annahme es seien dort 
Nullen.


Ich habe das Ding jetzt mal mit -fno-merge-constants übersetzt,
der Compiler schafft NOERR nach wie vor ins Stacksegment:
1
.bss            0x00000000001fe000      0xa2c
2
 *(.dynbss)
3
 *(.bss .bss.* .gnu.linkonce.b.*)
4
 .bss           0x00000000001fe000        0x0 asmstartport.o
5
 .bss           0x00000000001fe000        0x0 asmhandler.o
6
 .bss           0x00000000001fe000        0x1 coldport.o
7
                0x00000000001fe000                NOERR
8
 *fill*         0x00000000001fe001        0x3 00
9
 .bss           0x00000000001fe004        0x0 printport.o
10
 .bss           0x00000000001fe004        0x0 getlineport.o
11
 .bss           0x00000000001fe004        0x0 general.o
12
 .bss           0x00000000001fe004        0x0 asmprocport.o
13
 .bss           0x00000000001fe004        0x0 main.o
14
 .bss           0x00000000001fe004        0x0 bf.o


Ich habe aber was gefunden was funktioniert :-)

-fno-zero-initialized-in-bss:
1
                0x000000000080a98e                ERR03
2
                0x000000000080a9af                ERR02
3
                0x000000000080a9d1                ERR01
4
                0x000000000080a9f8                NOERR
5
                0x000000000080a9f9                MMASHELPMSG
6
                0x000000000080aa4b                HITKEYMSG

Das geht sogar wenn es ins ROM gebrutzelt ist:
1
MOTOROLA> md 1fe000
2
$001FE000:  $8AAA  $28AA  $AAAA  $0000  $0000  $0000  
3
$001FE00C:  $00AA  $8A00  $AA8A  $2A2A  $AAA8  $AAA8  
4
$001FE018:  $A2AA  $AAAA  $A8A8  $2AAA  $89AA  $88AA  
5
$001FE024:  $AAAA  $A2AA  $82AA  $AAAA  $AAAA  $AAAA  
6
$001FE030:  $2AAA  $82AA  $AAAA  $0AAA  $8AAA  $8EA2  
7
$001FE03C:  $AAAA  $AAAA  $AAAA  $A8AA  $82AA  $AAAA  
8
$001FE048:  $AA2A  $AA8A  $22AA  $A2AA  $AAA8  $AA8A  
9
$001FE054:  $A8AA  $AAA0  $AAAA  $AAAA  $AA22  $FFFF  
10
11
12
MOTOROLA>

BTW: ich habe dieses originale print() in printport.c wieder drin, das 
funktioniert also durchaus und hat den kleinsten Speicherverbrauch.
xprintf() funktioniert aber auch :-)


Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Holm Tiffe schrieb:
> Dann hätte der Compiler mal die und mal die Ansicht über das was ich
> machen will

Wahrscheinlich hat er deine Uralt-Funktionsprototypen gesehen und sich 
gedacht, daß Du dich eh' nicht um Standards scherst ;).

von Holm T. (Gast)


Lesenswert?

Immer auf die Kleinen! Ich wars doch aber gar nicht :-)
Gruß,

Holm

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Holm Tiffe schrieb:

> Ich finde es halt nur seltsam, dass der Ort an dem eine Variable
> angelegt wird von dessen initialisiertem Inhalt abhängig zu sein
> scheint.

Dass Variablen, die nur mit Nullen gefüllt sind, nicht mehr in .data
sondern in .bss landen, ist seit GCC 3.x so.  GCC 2.95 war der
letzte, bei dem man tunlichst sowas wie
1
static int foo = 0; /* Ich trau' dem C-Standard nicht und 
2
                       will ganz sicher sein, dass das wirklich
3
                       0 ist. :-) */

vermeiden musste, weil es das Binary um einen zusätzlichen
Initialwert 0 aufgebläht hat, obwohl .bss (per definitionem) die
gleiche Funktionalität bietet.

(Hatte dein Problem gestern abend nicht gleich mental erfasst.)

Diese Bemerkung von Markus:

Beitrag "Re: Initialisiertes Char Feld mit Länge 1 und Inhalt '\0'?"

beschreibt wohl dein eigentliches Problem: da werden Variablen
angelegt (die müssen im RAM sein, denn der Nutzer könnte sie ändern
wollen), obwohl eigentlich nur Konstanten gebraucht werden.

Wenn du natürlich .data und .bss nicht so benutzt, wie der Compiler
das für normal hält (beide liegen im RAM, aber .data wird beim Start
aus dem Image geladen), dann musst du dich ggf. händisch um die
daraus resultierenden Randprobleme kümmern.  (Ich habe auf die Schnelle
nicht versucht zu verstehen, was du da gegenüber der normalen
Vorgehensweise hier anders anstellst.  Eventuell sollten wir uns ja
doch mal am Telefon darüber unterhalten.)

>> Herzlichen Glückwunsch übrigens noch. ;-)
>
> Nach 14 Jahren Testbetrieb keine Ursache zur Aufregung.

:)

von Markus F. (mfro)


Lesenswert?

Mir ist mittlerweile auch siedend heiß und klar wie Nudelsuppe 
aufgegangen, warum -fno-merge-constants nix ändert. Hab' ich ja selber 
geschrieben: da gehts nicht um Konstanten, konsequenterweise faßt er die 
Arrays auch nicht an.

Und weil's mir keine Ruhe gelassen hat (man will hier ja schließlich 
auch was lernen ;) ) hab' ich das ganze Ding mit den Error-Strings 
einmal als char * und einmal als char[] durch den Compiler geschickt.

Auch wenn's dich vielleicht nicht mehr interessiert (es funktioniert ja 
schließlich): als char * Zeiger auf Stringliterale bleiben die Meldungen 
(alle) da, wo sie hingehören: im .data-Segment.

Außerdem wird das Programm dadurch nicht ganz unerheblich kleiner.

Könnte sich also trotzdem lohnen, da noch mal dranzufassen.

von Holm T. (Gast)


Lesenswert?

@Markus: Ich probiere das aus und werde Dich hier auf dem Laufenden 
halten, ich habe noch lange nicht die letzte Version in den ROM 
gebruzelt :-)

@J: Nu gugge da. Der Compiler der das das letzte Mal vorher fehlerfrei 
übersetzt hatte war ein gcc-2.95 m68k-coff. Damit wäre zumindest das 
abgeklärt. Du hast damals ein Perlscript gebastelt, das aus der 
Ladeliste die extern relevanten Symbole rauszieht, auf die ein 
hochgeladenes Programm zugreifen kann (z.B. dieses print()).
Das Script funktioniert scheinbar immer noch.

Betreffs der Zuordnung der Segmente: Ich habe im Wesentlichen einen 
Bereich mit ROM und einen Bereich mit RAM zur Verfügung und halte es für 
zweckmäßig unveränderliche Daten im ROM und veränderliche im RAM zu 
speichern, hier gehen wir wahrscheinlich konform.

Die C-Quelle zum FBUG ist hornalt und es wird eigentlich nirgends 
explizit auf die Segmentproblematik eingegangen, allerdings bringt das 
Ding halt eine eigene Initialisierung der Variablen in .bss nach dem 
Reset mit. Die Aufteilung ergab sich also im Endeffekt so ziemlich von 
selbst, der gcc hat gemerkt welche V. er nach .data und welche er nach 
.bss ablegen sollte, zumindest ist diese Aufteilung mehr oder weniger 
"von selbst" entstanden. Diese Sache mit dem NOERR war das bisher 
einzige Problem in dieser Richtung. Da .data halt unveränderlich ist und 
das so funktioniert, warum sollte ich den Kram erst umkopieren?

Dieser Debug-Monitor ist dazu gedacht in seinem RAM Programme testen zu 
können, auch schrittweise Abarbeitung und Manipulation der Daten ist 
drin. Er bringt ja sogar einen Assembler mit. Wenn der Prozessor über 
eine Exception stolpert, geht das Ding über Los bzw. 0x0 und wird 
vollständig neu geladen. Ich würde es für Kacke halten das Programm 
danach neu über die Serielle einfädeln zu müssen weil irgend Jemand 
unbedingt den RAM löschen möchte..

Wenn Du Dir das Theater im Einzelnen angucken willst, kannst Du mal 
unter http://www.tiffe.de/Robotron/Motorola/fbug gucken, ich habe gerade 
den aktuellen Stand da hoch geladen..

Gruß,

Holm

von Holm T. (Gast)


Lesenswert?

@Markus: Ich habe jetzt "char *ERRblah = "lolo\n" reingebastelt, Platz 
spart das eher nicht, eher im Gegentum:


Original mit char ERR01[] = "ERROR 01: illegal number of arguments\n";:
1
m68k-elf-ld -Tlinkscript -M=fbug.map -nostdlib -Ttext=0x00800000 -Tbss=0x001fe00
2
0 asmstartport.o asmhandler.o coldport.o  printport.o getlineport.o general.o as
3
mprocport.o main.o bf.o bm.o  bs.o da.o dc.o he.o lo.o rd.o rm.o tm.o mm.o md.o
4
go.o tr.o br.o  sd.o as.o disasm68.o asm68.o asmcode68.o handler.o conf.o  fprou
5
tines.o  68def.o rtc.o  -o fbug000TT.elf -L/usr/home/holm/cross/m68k/lib/gcc/m68
6
k-elf/4.6.2/m68000 -L/home/holm/cross/m68k/lib -L/home/holm/cross/m68k/m68k-elf/
7
lib/m68000 -lgcc -liberty -lc
8
m68k-elf-size fbug000TT.elf
9
   text    data     bss     dec     hex filename
10
  42598    4040    2600   49238    c056 fbug000TT.elf
11
m68k-elf-objdump -m68010 -S fbug000TT.elf >fbug000TT.disas

mit char *ERR01 = "ERROR 01: illegal number of arguments\n";:
1
m68k-elf-ld -Tlinkscript -M=fbug.map -nostdlib -Ttext=0x00800000 -Tbss=0x001fe00
2
0 asmstartport.o asmhandler.o coldport.o  printport.o getlineport.o general.o as
3
mprocport.o main.o bf.o bm.o  bs.o da.o dc.o he.o lo.o rd.o rm.o tm.o mm.o md.o
4
go.o tr.o br.o  sd.o as.o disasm68.o asm68.o asmcode68.o handler.o conf.o  fprou
5
tines.o  68def.o rtc.o  -o fbug000TT.elf -L/usr/home/holm/cross/m68k/lib/gcc/m68
6
k-elf/4.6.2/m68000 -L/home/holm/cross/m68k/lib -L/home/holm/cross/m68k/m68k-elf/
7
lib/m68000 -lgcc -liberty -lc
8
m68k-elf-size fbug000TT.elf
9
   text    data     bss     dec     hex filename
10
  42926    3752    2600   49278    c07e fbug000TT.elf
11
m68k-elf-objdump -m68010 -S fbug000TT.elf >fbug000TT.disas

und das Letzte nochmal ohne -fno-zero-initialized-in-bss:
1
m68k-elf-ld -Tlinkscript -M=fbug.map -nostdlib -Ttext=0x00800000 -Tbss=0x001fe00
2
0 asmstartport.o asmhandler.o coldport.o  printport.o getlineport.o general.o as
3
mprocport.o main.o bf.o bm.o  bs.o da.o dc.o he.o lo.o rd.o rm.o tm.o mm.o md.o
4
go.o tr.o br.o  sd.o as.o disasm68.o asm68.o asmcode68.o handler.o conf.o  fprou
5
tines.o  68def.o rtc.o  -o fbug000TT.elf -L/usr/home/holm/cross/m68k/lib/gcc/m68
6
k-elf/4.6.2/m68000 -L/home/holm/cross/m68k/lib -L/home/holm/cross/m68k/m68k-elf/
7
lib/m68000 -lgcc -liberty -lc
8
m68k-elf-size fbug000TT.elf
9
   text    data     bss     dec     hex filename
10
  42926    3752    2600   49278    c07e fbug000TT.elf
11
m68k-elf-objdump -m68010 -S fbug000TT.elf >fbug000TT.disas

Das Ding spart also Platz im .data und braucht mehr in .text.

Gruß,

Holm

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

1) Mit constant-merging hat das ganze nix zu tun; 0-initialisierte Daten 
leben eben in .bss (oder common)

2) Deine Daten können nicht im ROM oegen weil sie nicht const sind. Mit 
const sollten sie in .rodata landen.

3) Für den leeren String: Anstatt char S[] = "" einfach const char S[] = 
"".  Falls dein GCC dann immer noch nach .bss legt: 
-fno-zero-initialized-in-bss.

von Holm T. (Gast)


Lesenswert?

Johann L. schrieb:
> 1) Mit constant-merging hat das ganze nix zu tun; 0-initialisierte Daten
> leben eben in .bss (oder common)
>

Das hat Markus schon erzählt.


> 2) Deine Daten können nicht im ROM oegen weil sie nicht const sind. Mit
> const sollten sie in .rodata landen.

Es steht Dir frei auf meiner Webseite die fbug*map Datei runter zu laden 
und rein zu gucken.

>
> 3) Für den leeren String: Anstatt char S[] = "" einfach const char S[] =
> "".  Falls dein GCC dann immer noch nach .bss legt:
> -fno-zero-initialized-in-bss.


Aha... das hatte Holm oben schon rausbekommen...

Danke für die Bekräftigung und das Anzweifeln unserer Aussagen.

..oder häh?

Gruß,

Holm

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Holm Tiffe schrieb:
> Johann L. schrieb:
>> 2) Deine Daten können nicht im ROM oegen weil sie nicht const sind. Mit
>> const sollten sie in .rodata landen.
>
> Es steht Dir frei auf meiner Webseite die fbug*map Datei runter zu laden
> und rein zu gucken.

Der Compiler erzeugt Code, der dem C-Standard entsprechen.  Dazu muß er 
bestimmte Annahmen darüber machen, wie Binutils (oder allgemeiner 
Assembler / Linker / Locator) Daten ablegen und Sections benennen / 
behandeln.  ELF-Standard ist, schreibbare Daten in .bss oder .data zu 
legen.  Wenn du in deiner tollden Datei die Sections so verbiegst, dass 
das in Undefined Behavior resultiert, dann bekommst du eben Undefined 
Behaviour ;-)

Das Problem war also nicht bei den Tools sondern vor des Tastatur (bzw. 
in fbug*map -- was immer da drinsteht).

Für solche Zwecke ist __attribute__((__section__(".rodata.mysection"))) 
naheliegend, um die Daten (oder Funktion) in eine bestimmte 
Input-Section zu legen und diese dann nach Gusto zu behandeln.

> ..oder häh?

von Markus F. (mfro)


Lesenswert?

Johann L. schrieb:
> Holm Tiffe schrieb:
>> Johann L. schrieb:
>>> 2) Deine Daten können nicht im ROM oegen weil sie nicht const sind. Mit
>>> const sollten sie in .rodata landen.
>>
>> Es steht Dir frei auf meiner Webseite die fbug*map Datei runter zu laden
>> und rein zu gucken.
>

Uiuiuiuiui.


_1: Ich_hab_recht();
   nein_ich();
   goto _1;

> Der Compiler erzeugt Code, der dem C-Standard entsprechen.  Dazu muß er
> bestimmte Annahmen darüber machen, wie Binutils (oder allgemeiner
> Assembler / Linker / Locator) Daten ablegen und Sections benennen /
> behandeln.  ELF-Standard ist, schreibbare Daten in .bss oder .data zu
> legen.  Wenn du in deiner tollden Datei die Sections so verbiegst, dass
> das in Undefined Behavior resultiert, dann bekommst du eben Undefined
> Behaviour ;-)
>
Dem Compiler ist völlig wurscht, welche Sections wo liegen und als 
Standard gibt's hier nur einen: das ELF-Dateiformat. Der Begriff 
"Undefined Behaviour" taucht dort nur einmal auf: beim Note-Segment, und 
das kommt hier keins vor.

Der Code ist uralt und wer sich die Mühe macht, mal reinzuschauen, sieht 
als erstes

- Copyright Motorola Inc. 1989

Da war das ELF-Format noch gar nicht erfunden ;). Wenn ich mich nicht 
sehr täusche, gab's die erste öffentliche Spec (von SCO und AT&T, beides 
damals noch recht veritable Unternehmen) erst ein Jahr später...

Folglich mußten die Jungs von Motorola noch mit COFF (oder gar a.out) 
werkeln und das kannte nur .text, .data und .bss, über readonly-Segmente 
wurde nix gesagt. Schaut man in den Code rein, sieht man, daß da jemand 
peinlich genau aufgepaßt hat, Variablen so oft wie möglich entweder in 
Registern oder auf dem Stack zu halten, und nur wo das nicht ging, 
wurden sie ins .bss gepackt (also erst zur Laufzeit initialisiert).

Ist also völlig wurscht, wo man das .data-Segment hinsteckt, das wird in 
diesem Programm sowieso nur gelesen.

Im ELF-Standard steht meines Wissens nach übrigens nicht, daß das 
.data-Segment immer R/W sein muß.

Wenn da irgendwas "richtig falsch" ist, dann höchstens, daß das 
.bss-Segment nicht vom Startupcode gelöscht wird. Das steht nämlich im 
ELF-Standard.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Das undefinierte Verhalten ergibt sich auf C-Ebene, nicht auf ELF-Ebene.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Markus F. schrieb:
> Da war das ELF-Format noch gar nicht erfunden ;)

Erfunden war es da wohl gerade schon, allerdings dauerte es noch ein
paar Jahre (bis ca. Mitte der 1990er), bis es sich auch jenseits von
System V allgemein durchgesetzt hatte.

von Holm T. (Gast)


Lesenswert?

Hallo Leute...es interessiert mich die Bohne in welchem Segment der 
Lader den Kram unterbringt, mein Target sind 2 Eproms und veränderliche 
Daten müssen ins RAM. Ich brauche keine ELF Datei sondern ein Binary das 
ich brennen kann, ELF oder COFF sind nur ein Zwischenschritt, völlig 
irrelevant.
Das Compilat dieser alten Software ist ein direkt auf der Hardware 
laufender Debugger der auch durchaus seine eigenen Veränderlichen 
Variablen initialisiert. Dafür paßt auch das der Debugger nur Stack und 
Register verwenden möchte, logischerweise soll der nur einen kleinen 
Fußabdruck im System hinterlassen.

Punkt.

Nummero 2, und daran kämpfe ich noch, ist ein Setup für Programme die 
der Debugger laden kann (srec) und dabei sollte die Verwendbarkeit von 
Unterprogrammen das Debuggers gewährleistet sein. Hier unterhalte ich 
mich gerne über was in die ELF Segmente wo einsortiert wird. Da darf 
auch gerne das .bss initialisiert werden. So weit war ich vor Jahren mit 
dem Ding schon einmal, mit GCC2.95.

Logischerweise erzeugte meine alte Version des Crosscompilers COFF und 
ich hatte das auch für die Jetzige angepeilt. Ich habe den Compiler nur 
nochmal neu und für ELF auf die Beine gestellt weil Markus das so 
vorgeschlagen hat.
Das ist alles im Thread neben an (den ich im ersten Posting verlinkt 
hatte) zu lesen. Seltsamerweise hielten sich aber die Vorschläge Anderer 
in diesem Thread arg in Grenzen.

Um ehrlich zu sein geht mir der ganze ELF-Kuddelmuddel bereits gehörig 
auf den Senkel weil es den ganzen Kram unnötig verkompliziert. Das bei 
COFF noch sehr übersichtliche Linkerscript hat sich mit ELF in einen 
Wust aus Schrott verwandelt durch den kaum einer durch sieht und von dem 
95% nur Rauschen ist.

Mit der Ganzen newlib/libgloss Geschichte kämpfe ich derzeit und da 
gibts auch so völlig überhaupt kein Beispiel für ELF Output im Newlib 
Tree bei M68k...
Die Konfiguration des Krams ist auch reichlich fragwürdig, wieso wird 
meine BSP Package automatisch auch für MC68060 übersetzt? Weil das dann 
schön lange dauert? Dann ist das auch der Grund warum ein MVME137 auch 
für mc68000 übersetzt wird. So ein Schwachsinn.

@Markus:
>Wenn da irgendwas "richtig falsch" ist, dann höchstens, daß das
>.bss-Segment nicht vom Startupcode gelöscht wird. Das steht nämlich im
>ELF-Standard.

..offensichtlich so falsch, das es dafür sogar einen Compiler Schalter 
gibt?

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Holm Tiffe schrieb:
> ..offensichtlich so falsch, das es dafür sogar einen Compiler Schalter
> gibt?

Hatten wir schon. Es soll ja Leute geben, die sich nicht um Standards 
scheren...

Die sollen auch ihren persönlchen Schalter haben ;).

von Markus F. (mfro)


Lesenswert?

Das Linker-Skript muß übrigens nicht mal ansatzweise so kompliziert 
sein. Zumindest nicht, wenn Du nur C haben willst:
1
MEMORY
2
{
3
   rom (rx) : ORIGIN = start, LENGTH = laenge
4
   ram (WX) : ORIGIN = ram_start, LENGTH = ram_laenge
5
}
6
7
SECTIONS
8
{
9
  .rom :
10
  {
11
           start.o(.text) 
12
           ... alles, was ins ROM soll ...
13
     *(.rodata)
14
     *(.rodata.*)
15
  } > rom
16
17
  .ram :
18
  {
19
    . = ALIGN(4);
20
    *(.data)
21
    *(.bss)
22
  } > ram
23
}

Müsste eigentlich völlig ausreichen. Vielleicht hab' ich auch ein 
Fitzelchen vergessen, aber sehr viel mehr braucht's nicht.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Holm Tiffe schrieb:
> Um ehrlich zu sein geht mir der ganze ELF-Kuddelmuddel bereits gehörig
> auf den Senkel weil es den ganzen Kram unnötig verkompliziert.

Holm,

zu COFF-Zeiten gab es einfach keinerlei Weg, wie man ein C-Programm
so compiliert, dass daraus sinnvoll ROM-Code erzeugt werden konnte.
Die PDP-11 hatte halt keinen ROM, und auch Nachfolgesysteme nicht.
Folglich gab's aus Sicht des Compilers immer nur RAM, der dann
teilweise mit Nullen, teilweise mit Daten aus dem Binary initialisiert
wird.

Dass sie nun bei Motorola 1989 da irgendwie was draus gemacht haben,
was das bestmöglich auf eine ROM-Version abbildet, ist ja OK.  Aber
dafür mussten sie halt Annahmen treffen, wie man den damaligen
Compiler so verbiegt, dass das bestmöglich passt.  Davon darfst du
aber nicht erwarten, dass auch zweieinhalb Jahrzehnte später sich noch
jeder Compiler mit dieser Verbiegung genau so verhält wie der
damalige, insbesondere natürlich dadurch schon nicht, dass es
mittlerweile Möglichkeiten gibt, dem Compiler sowas wie ROM-Daten
auf ganz natürliche Weise beizubiegen.

Nun kannst du entweder hingehen und den alten Code auf das Niveau
aktueller Compiler heben (vermutlich würden dabei auch gleich noch
massig Bugs zutage kommen, die heutzutage die statische Codeanalyse
so rausfindet), oder du gehst den pragmatischen Weg und verdrehst
eben den aktuellen Compiler so, dass er (weitgehend) den damaligen
Gepflogenheiten entspricht.  Was anderes ist letztlich dieses
-fno-zero-initialized-in-bss nicht.

von Holm T. (Gast)


Lesenswert?

@Markus:

Werde ich wie immer ausprobieren.

@J:

Das Thema ist an und für sich schon durch. Der Debugger lief schon 
vorher nur mit der vergriesgnaddelten Ausgabe.
Seit -fno-zero-initialized-in-bss ist auch das behoben und ich bastele 
da derzeit gar nicht herum. Ich muß mir den primitiven Receiver Code für 
die 68681 noch mal zu Gemüte führen weil mein PC das Ding beim Senden 
von S-Records scheinbar (ich weiß es nicht genau) manchmal über den 
Haufen schiebt. Das wäre eine Frage der Initialisierung, das Ding kann 
bei vollem FIFO selbstständig mit RTS wackeln (ein Feature das heute zu 
Tage scheinbar
auch Keiner mehr in Hardware implementiert)...das ist Alles.
Es lohnt sich eigentlich nicht weiter darüber zu diskutieren.

Derzeit bastele ich an dem oben angesprochenen Punkt 2, einer passenden 
libgloss damit ich Executables für diese "Plattform" bauen und als 
S-Record da rüber schieben kann. Das Ding verhaspelt sich aber derzeit 
irgendwo im atexit Aufruf noch bevor main überhaupt angesprungen wird. 
atexit macht da irgendwelche Schweinerein auf dem Stack in dessen Folge 
ein Zugriff auf eine Gegend ohne Speicher und damit ein Trap erfolgt.
Offensichtlich befindet sich da nicht das auf dem Stack was sich die 
Manipulation so einbildet. Nicht besonders hilfreich ist dabei die 
Tatsache das ich zu wenig über den M68k weiß und die Mnemonics im 
Wesentlichen nicht kenne.
1
  p = _GLOBAL_REENT->_atexit;
2
    2284:       2679 0000 43c8  moveal 43c8 <_global_impure_ptr>,%a3
3
    228a:       246b 0048       moveal %a3@(72),%a2
4
  if (p == NULL)
5
    228e:       b4fc 0000       cmpaw #0,%a2
6
    2292:       6608            bnes 229c <__register_exitproc+0x24>
7
    _GLOBAL_REENT->_atexit = p = &_GLOBAL_REENT->_atexit0;
8
    2294:       45eb 004c       lea %a3@(76),%a2
9
    2298:       274a 0048       movel %a2,%a3@(72)
10
  if (p->_ind >= _ATEXIT_SIZE)
11
    229c:       701f            moveq #31,%d0
12
    229e:       b0aa 0004       cmpl %a2@(4),%d0
13
    22a2:       6c2a            bges 22ce <__register_exitproc+0x56>
14
#ifndef _ATEXIT_DYNAMIC_ALLOC
15
      return -1;
16
#else
17
      /* Don't dynamically allocate the atexit array if malloc is not
18
         available.  */
19
      if (!malloc)
20
    22a4:       41f9 0000 0000  lea 0 <__DYNAMIC>,%a0
21
    22aa:       b0fc 0000       cmpaw #0,%a0
22
    22ae:       6700 00a0       beqw 2350 <__register_exitproc+0xd8>
23
        return -1;
24
25
      p = (struct _atexit *) malloc (sizeof *p);
26
    22b2:       4878 008c       pea 8c <__DYNAMIC+0x8c>
27
    22b6:       4e90            jsr %a0@
28
    22b8:       2440            moveal %d0,%a2
29
      if (p == NULL)
30
    22ba:       588f            addql #4,%sp
31
    22bc:       4a80            tstl %d0
32
    22be:       6700 0090       beqw 2350 <__register_exitproc+0xd8>
33
#ifndef __SINGLE_THREAD__
34
          __lock_release_recursive(__atexit_lock);
35
#endif
36
          return -1;
37
        }
38
      p->_ind = 0;
39
    22c2:       42aa 0004       clrl %a2@(4)
40
      p->_next = _GLOBAL_REENT->_atexit;
41
    22c6:       24ab 0048       movel %a3@(72),%a2@
42
      _GLOBAL_REENT->_atexit = p;
43
    22ca:       2740 0048       movel %d0,%a3@(72)
44
      p->_on_exit_args._is_cxa = 0;

Gesundheit!
Ich brauche da ein Bisschen Zeit und Nerven wie es aussieht.

Wie schon gesagt, das Problem oben halte ich für gegessen...

BTW: >die PDP-11 hatte halt keinen ROM

Darüber kann man sich zanken :-)
meine 11/83 hier unter dem Tisch schon, nur ist da garantiert kein Code 
drin der mit einem C-Compiler erzeugt wurde.

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Was da an deinem Programm klemmt, ist aus dem Disassembly nicht zu 
erkennen.

Jedenfalls würde ich spätestens jetzt das .bss-Segment löschen ;).

Was anderes:

Mir ist aufgefallen, daß in deinen Makefiles die Option "-ffreestanding" 
fehlt. Der gcc geht dann davon aus, daß er Code für ein komplettes 
"hosted environment" generieren soll.

Muß nicht unbedingt die Ursache sein, aber das ist in deinem Fall 
möglicherweise gar nicht mal so gut...

von Holm T. (Gast)


Lesenswert?

Markus mach mich doch nicht alle. Mein Programm klemmt gar nicht.
Vergiß erst mal die Sache mit dem bss und höre mir mal jetzt hier zu,
das -ffreestanding vergesse ich dabei nicht.

Dieser Debugger soll ein geladenes Programm starten können, demzufolge 
gibt es für diese ladbaren Programme ein Setup mit nur RAM, also auch 
.text, .data .bvss und .hastenigesehen alles RAM.
Ich kann ein Programm laden und ich kann es anspringen (auch 
schrittweise abarbeiten) aber noh bevor irgend was losgeht bekomme ich 
einen illegalen Instruktion Trap in einer "frame_dummy" die wohl der gcc 
erzeugt.

Hier erst mal die Reste Deines Linkerscripts:
1
STARTUP(crt0.o)
2
OUTPUT_ARCH(m68k)
3
/* Uncomment this if you want srecords. This is needed for a.out
4
 * if you plan to use GDB.
5
OUTPUT_FORMAT(srec)
6
 */
7
8
SEARCH_DIR(.)
9
GROUP(-lkatce -lc -lgcc)
10
__DYNAMIC  =  0;
11
12
MEMORY
13
{
14
   rom (rx) : ORIGIN = 0x800000, LENGTH = 128K
15
   ram (rwx) : ORIGIN = 0x1000, LENGTH = 512K-8K
16
17
18
}
19
20
PROVIDE (__stack = 512K - 8k);
21
22
23
24
PROVIDE (hardware_init_hook = 0);
25
PROVIDE (_hardware_init_hook = 0);
26
PROVIDE (software_init_hook = 0);
27
PROVIDE (_software_init_hook = 0);
28
29
30
SECTIONS
31
{
32
  .text :
33
  {
34
   CREATE_OBJECT_SYMBOLS
35
    *(.text .text.*)
36
    . = ALIGN(0x4);
37
           crt0.o(.text)
38
     *(.rodata)
39
     *(.rodata.*)
40
    . = ALIGN(0x4);
41
    __INIT_SECTION__ = . ;
42
    *(.init)
43
    SHORT (0x4e75)      /* rts */
44
45
    . = ALIGN(0x4);
46
    __FINI_SECTION__ = . ;
47
    *(.fini)
48
    SHORT (0x4e75)      /* rts */
49
    _etext = .;
50
51
  } > ram
52
53
  .data :
54
  {
55
    *(.data .data.*)
56
    _edata = .;
57
  } > ram
58
 .bss :
59
  {
60
    . = ALIGN(4);
61
    __bss_start = . ;
62
    *(.shbss)
63
    *(.bss .bss.*)
64
    *(COMMON)
65
    _end =  ALIGN (0x8);
66
    __end = _end;
67
  } > ram


Ich habe dann noch unmittelbar hinter (.rodata.*) . = ALIGN(0x4);
     *(.eh_frame) eingefügt, wobei mir nicht klar ist was das machen 
soll, aber ich bin in dem frame_dummy Zeug darüber gestolpert.
Geht das Script erst mal so?

Symptom ist, das nach dem löschen des .bss (jaha, huhu..) atexit 
aufgerufen wird um eventuell irgend welche Funktionen einzubinden die 
nach exit gerufen werden sollen. Danach soll irgendwann mal main 
angesprungen werden, aber es kracht vorher und zwar hier:
1
000010f8 <frame_dummy>:
2
    10f8:       4e56 0000       linkw %fp,#0
3
    10fc:       41f9 0000 0000  lea 0 <__DYNAMIC>,%a0
4
    1102:       4a88            .short 0x4a88
5
    1104:       6710            beqs 1116 <frame_dummy+0x1e>
6
    1106:       4879 0000 3966  pea 3966 <object.2327>
7
    110c:       4879 0000 3424  pea 3424 <__EH_FRAME_BEGIN__>
8
    1112:       4e90            jsr %a0@
9
    1114:       508f            addql #8,%sp
10
    1116:       4ab9 0000 395c  tstl 395c <__JCR_END__>
11
    111c:       6714            beqs 1132 <frame_dummy+0x3a>
12
    111e:       41f9 0000 0000  lea 0 <__DYNAMIC>,%a0
13
    1124:       4a88            .short 0x4a88
14
    1126:       670a            beqs 1132 <frame_dummy+0x3a>
15
    1128:       4879 0000 395c  pea 395c <__JCR_END__>
16
    112e:       4e90            jsr %a0@
17
    1130:       588f            addql #4,%sp
18
    1132:       4e5e            unlk %fp
19
    1134:       4e75            rts
20
21
00001136 <call_frame_dummy>:
22
    1136:       4e56 0000       linkw %fp,#0
23
    113a:       4e5e            unlk %fp
24
    113c:       4e75            rts

auf Zeile 1102. Dieses .short 0x4a88 ist Irgendwas aber keine gültige 
Instruktion.
1
Trace at $00001102
2
PC   =$00001102   SR   =$00002704   USP  =$00001B00   
3
SSP  =$0007DFE8   VBR  =$00000000   SFC  =$00000000   DFC  =$00000000   
4
5
D0   =$00000000   D1   =$00000008   D2   =$00000000   D3   =$00000000   
6
D4   =$00000000   D5   =$00000000   D6   =$00000000   D7   =$00000000   
7
8
A0   =$00000000   A1   =$00000000   A2   =$00000000   A3   =$00000000   
9
A4   =$00000000   A5   =$00000000   A6   =$0007DFE8   A7   =$0007DFE8   
10
11
12
$00001102 4A88            DC.W          ?  
13
14
MOTOROLA> 
15
Illegal instruction at $00001102
16
17
PC   =$00001102   SR   =$0000A704   USP  =$00001B00   
18
SSP  =$0007DFE8   VBR  =$00000000   SFC  =$00000000   DFC  =$00000000   
19
20
D0   =$00000000   D1   =$00000008   D2   =$00000000   D3   =$00000000  D4   =$00000000   D5   =$00000000   D6   =$00000000   D7   =$00000000   
21
22
A0   =$00000000   A1   =$00000000   A2   =$00000000   A3   =$00000000   
23
A4   =$00000000   A5   =$00000000   A6   =$0007DFE8   A7   =$0007DFE8   
24
25
26
MOTOROLA>

Wie auch der wegen nicht gelöschtem .bss nicht funktionierende debugger 
bestätigt.
Hast Du ne Ahnung was das eigentlich werden sollte?

Compileroptionen beim übersetzen waren Folgende:
1
m68k-elf-gcc fbug.o ctest.o -L/home/holm/cross/m68k/m68k-elf/lib/m68000 -lgcc -lc -lkatce -m68010 -Xlinker -Tkatce.ld -Xlinker -Map -Xlinker memmap  -Xlinker --oformat -Xlinker elf32-m68k  -lm -lc -o ctest.elf
2
m68k-elf-objcopy -j .text -j .data -S -I elf32-m68k -O srec ctest.elf ctest.srec
3
m68k-elf-size ctest.srec
4
   text    data     bss     dec     hex filename
5
      0   10572       0   10572    294c ctest.srec

Mein eigentliches Programm sieht in Assembler so aus:
1
00001136 <call_frame_dummy>:
2
    1136:       4e56 0000       linkw %fp,#0
3
    113a:       4e5e            unlk %fp
4
    113c:       4e75            rts
5
        ...
6
7
00001140 <_start>:
8
    1140:       4eb9 0000 1148  jsr 1148 <main>
9
    1146:       4afc            illegal
10
11
00001148 <main>:
12
13
14
main()
15
{
16
17
printf("hello world\n");
18
    1148:       4879 0000 3414  pea 3414 <__sf_fake_stdin+0x20>
19
    114e:       4eb9 0000 124c  jsr 124c <puts>
20
    1154:       588f            addql #4,%sp
21
22
}
23
    1156:       4e75            rts
24
25
00001158 <atexit>:
26
27
int
28
_DEFUN (atexit,
29
        (fn),
30
        _VOID _EXFNPTR(fn, (_VOID)))
31
{
32
    1158:       4e56 0000       linkw %fp,#0
33
  return __register_exitproc (__et_atexit, fn, NULL, NULL);
34
    115c:       42a7            clrl %sp@-
35
    115e:       42a7            clrl %sp@-
36
    1160:       2f2e 0008       movel %fp@(8),%sp@-
37
    1164:       42a7            clrl %sp@-
38
    1166:       4eb9 0000 1280  jsr 1280 <__register_exitproc>
39
}
40
    116c:       4e5e            unlk %fp
41
    116e:       4e75            rts

Klar ist, das es auf 1146 auch scherbeln wird, weil ich die definition 
von _exit verschwinden lassen habe, das kommt dann wieder wenn ich erst 
mal bis zu main() komme...

Gruß,

Holm

von Holm T. (Gast)


Lesenswert?

..ich weiß was das ist, es ist ein MC68020 Befehl der A0 auf 0 testet, 
den gibts aber am 68010 nicht.

Ursache ist, das der gcc das falsche certbegin.o dazu linkt:
1
 92525 m68k-elf-gcc RET   stat 0
2
 92525 m68k-elf-gcc CALL  access(0x800cc31d0,0x4<R_OK>)
3
 92525 m68k-elf-gcc NAMI  "/usr/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/crtbegin.o"
4
 92525 m68k-elf-gcc RET   access 0

er müßte aber
1
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5206e/crtbegin.o
2
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5208/crtbegin.o
3
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5329/crtbegin.o
4
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m68040/crtbegin.o
5
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m68040/softfp/crtbegin.o
6
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5407/crtbegin.o
7
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m54455/crtbegin.o
8
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/mcpu32/crtbegin.o
9
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5206/crtbegin.o
10
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/crtbegin.o
11
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m68000/crtbegin.o
12
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5475/crtbegin.o
13
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5475/softfp/crtbegin.o
14
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/mfidoa/softfp/crtbegin.o
15
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/mfidoa/crtbegin.o
16
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m51qe/crtbegin.o
17
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/softfp/crtbegin.o
18
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m5307/crtbegin.o
19
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m68060/crtbegin.o
20
/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m68060/softfp/crtbegin.o

das aus dem m68000 directory nehmen.

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

0x4a88 ist ein
1
tst.l a0

und das ist ein gültiger m68k-Befehl.

Bloß nicht auf einem mc68000/10 ;).

Irgendwas stimmt mit deinen Compileroptionen noch nicht...

von Markus F. (mfro)


Lesenswert?

o.k., da bist Du auch schon drauf gekommen ;)

Wie sieht dein Linker-Aufruf aus?

Ach, da oben steht er ja.

Probier' mal das hier stattdessen:
1
m68k-elf-gcc -mcpu=68000 fbug.o ctest.o -lkatce -Wl,-Tkatce.ld -Wl,-Map -Wl,memmap -Wl,-oformat=elf32-m68k -lm -o ctest.elf

So ähnlich funzt's bei mir. Der m68k-gcc ist ein Multilib-gcc, seine 
Libraries sucht er selber je nach verwendeter Architektur.

P.S.: was sagt bei dir ein
1
m68k-elf-gcc -print-multi-lib
?

: Bearbeitet durch User
von Holm T. (Gast)


Lesenswert?

Ja, hatte ich schon ausprobiert. Reichlich doof das der $irgendeinen 
Prozessor > als 68000 als default nimmt wenn er mit m68010 nichts 
anzufangen weiß... damit gehts, ich habe zumindest das "Hello World 
schon gesehen..

Ich muß mein Momory-Layout im Debugger nochmal durchsehen...

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Holm Tiffe schrieb:
> als 68000 als default

das hängt davon ab, welchen Default Du beim configure (deines Compilers) 
vorgegeben hast.

Bei mir erwartet (und linkt) er M68000-Code, wenn ich keine Architektur 
angebe.

von Holm T. (Gast)


Lesenswert?

...Ja, TARGET_CPU_DEFAULT... habe ich indessen gefunden und werde das 
evtl. ändern.

Mal was Anderes.

Manchmal laufen meine Programme .. und manchmal nicht.

Nein, ist kein Zufall.

Da gibts eine Funktion
1
0000438c <__do_global_ctors_aux>:
2
    438c:       4e56 0000       linkw %fp,#0
3
    4390:       2f0a            movel %a2,%sp@-
4
    4392:       2079 0000 495c  moveal 495c <_edata>,%a0
5
    4398:       70ff            moveq #-1,%d0
6
    439a:       b088            cmpl %a0,%d0
7
    439c:       6710            beqs 43ae <__do_global_ctors_aux+0x22>
8
    439e:       45f9 0000 495c  lea 495c <_edata>,%a2
9
    43a4:       4e90            jsr %a0@
10
    43a6:       2062            moveal %a2@-,%a0
11
    43a8:       70ff            moveq #-1,%d0
12
    43aa:       b088            cmpl %a0,%d0
13
    43ac:       66f6            bnes 43a4 <__do_global_ctors_aux+0x18>
14
    43ae:       246e fffc       moveal %fp@(-4),%a2
15
    43b2:       4e5e            unlk %fp
16
    43b4:       4e75            rts

aus den Tiefen des gcc die da interessiert nach guckt ob in _edata
1
SECTIONS
2
{
3
  .text :
4
  {
5
   CREATE_OBJECT_SYMBOLS
6
  
7
.....
8
  .data :
9
  {
10
    *(.data .data.*)
11
    _edata = .;
12
  } > ram
13
14
  .bss :
15
  {
16
...

Ein Funktionspointer oder 0xffffffff abgelegt ist. Wenn das nicht 
0xffffffff ist springt das Teil diese Funktion an.

Das ist Soweit chic, als das einzige auftreten von _edata im gesamten 
Binary in dieser Funktion ist und das Ding, da es ja auch keine Variable 
ist und auch nicht Stack undefiniert ist. Damit springt das Teil 
fröhlich ins Gelände...


Soviel ich weiß brauche ich weder Constructoren noch Destructoren wenn 
ich mit lang=c konfiguriert habe, wie werde ich diesen Mist los?

Gruß,

Holm

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Holm Tiffe schrieb:

> Soviel ich weiß brauche ich weder Constructoren noch Destructoren wenn
> ich mit lang=c konfiguriert habe, wie werde ich diesen Mist los?

Vielleicht solltest du ja den Startup-Code mal unter die Lupe nehmen
(im Sourcecode, meine ich)?

Eventuell könnte es auch helfen, dass du einfach eine Funktion mit
linkst:
1
void __do_global_ctors_aux(void)
2
{
3
  /* do nothing */
4
}

und dann drauf hoffst, dass das gleichnamige Pendant aus dem
Startup-Code dadurch überschrieben wird.

von Markus F. (mfro)


Lesenswert?

Holm Tiffe schrieb:
> wie werde ich diesen Mist los?

do_global_ctors_aux() ist in crtbegin.o definiert (das läßt sich mit dem 
Linker nicht übersteuern).

Ich linke embedded-Programme immer mit -nostdlib. Dann ist weder 
crtbegin.o noch libc im Programm, letzteres kann aber hinzugelinkt 
werden, wenn man das will (ich will's nicht).

Natürlich braucht's dann einen eigenen Startup-Code.

Ansonsten schreib' halt in Gottes Namen 'ne -1 dahin, wo er sie haben 
will ;).

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.