...es gibt da eine Funktion getcount() in general.c:
1
getcount(str,size,strt,err)
2
char*str;/* string with <range> on it */
3
intsize;/* 1,2 or 4; the number of bytes from <size> */
4
intstrt;/* starting address */
5
charerr[];/* 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
charNOERR[]="";
2
charERR01[]="ERROR 01: illegal number of arguments\n";
3
charERR02[]="ERROR 02: illegal address syntax\n";
4
charERR03[]="ERROR 03: illegal number syntax\n";
5
charERR04[]="ERROR 04: illegal option\n";
6
charERR05[]="ERROR 05: insufficient room to insert data\n";
7
charERR06[]="ERROR 06: breakpoint table is full\n";
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
charNOERR[]={0};
daran überhaupt Nichts. Schreibe ich aber
1
charNOERR[]={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
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.
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. ;-)
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
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
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... ?
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.
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
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
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
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 ;).
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
staticintfoo=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.
:)
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.
@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
@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) 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.
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
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?
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.
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.
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
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 ;).
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.
@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.
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
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...
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.
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:
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
..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:
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
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
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.
...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
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.
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 ;).