Forum: Compiler & IDEs Linker linkt inkonsistent


von Simon H. (simi)


Lesenswert?

Hallo zusammen,

ich habe ein Problem, das mich langsam in den Wahnsinn treibt. Vielleich
fällt dem Einen oder Andern ja etwas ein, was ich noch checken könnte.

Also:

Ich habe ein Makefile-basiertes STM32-C++Projekt in Eclipse neu
aufgesetzt.
crt0 und linker Script von ST, modifiziert von Matrin Thomas. Makefile
auch von der selben Quelle.

Das hat mal ganz ordentlich funktioniert, zumindest insofern, dass die
statischen Konstruktoren ausgeführt wurden. Malloc von Newlib konnte ich
auch einbinden, alles wunderbar. Dann habe ich FreeRTOS eingebaut (hat
in einem anderen Projekt perfekt funktioniert).

Und jetzt habe ich plötzlich folgendes Problem:

crt0 wird ausgeführt, aber beim Aufruf von main() springt der mir an die
total falsche Stelle. Will heissen: main() ist laut Map- und Listfile an
einer bestimmten Adresse A zu finden. crt0 springt aber an 'ne total
(wirklich völlig) andere Adresse B. Wenn ich den Debuger vor dem
main()-Aufruf stoppe und von Hand die Adresse A in's R3-Register
schreibe, springt er dahin, wo er hinsoll, nämlich zu main().

Was ich schon versucht habe: Neues Projekt aufsetzen und alle Files neu
einlesen. Natürlich make clean, mindestens ein Dutzend Mal gecheckt,
dass alle Object Files gelöscht sind, main mit extern "C" deklariert,
main mal als c-File statt cpp compiliert (natürlich im Makefile
angepasst), Code-Optimierungen rausgenommen. Wenn ich main.cpp ganz
lösche, moost der Linker, er fände main() nicht. Also sollte da auch
keine Leiche rumliegen.

So. Ich weiss, das schreit jetzt nach der Kristallkugel. Ich erwarte
natürlich auch keine Antwort im Sinne von: "Hey, diesen Knopf musst Du
drücken", sondern eher Tipps, in welche Richtung man denn eventuell noch
suchen könnte (z.B. irgendwelche Projekt-Einträge im Eclipse???)

Gruss
Simon

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


Lesenswert?

Simon Huwyler schrieb:
> crt0 springt aber an 'ne total
> (wirklich völlig) andere Adresse B.

Wohin denn?  Kannst du über die Symboltabelle rausfinden, was an
dieser Stelle ist?

Ansonsten bleibt dir wohl nicht viel anderes übrig als zu analysieren
(auf Ebene des Disassemblers), was genau bis zu diesem Punkt passiert.

von Simon H. (simi)


Lesenswert?

Das ist ja gerade das Merkwürdige: Er springt irgendwo hin, wo weit und 
breit kein Symbol ist. Ich weiss gerade nicht auswendig, in welchches 
Modul, aber eben, einfach mittig irgendwo hinein.

Auf Ebene des Disassemblers ist alles wunderbar nachvollziehbar. Er lädt 
R3 mit 'ner Adresse, die er für die richtige Einsprungadresse hält und 
springt diese dann an. Im List-File lügt er mich sogar fadengerade und 
explizit an, dass das die Adresse von "main" sei. Und im selben 
List-File steht main an einer total anderen Adresse.

Irgendwie schon seeeeeehr merkwürdig...

Ich bin fast überzeugt, dass irgendwo irgendeine Leiche rumliegt. Nur - 
was ausser den Object-Files kann ich noch bereinigen?

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


Lesenswert?

Dann wirst du dir wohl oder übel mal ein Linkermapfile erzeugen müssen.
Die Dinger sind zwar "close to unreadable", aber recht ausführlich.

von Simon H. (simi)


Lesenswert?

hmmm, ja. Was mir noch eingefallen ist: Der Linker kann ja angewiesen 
werden, Code, "versetzt" abzulegen, z.B. den Code in's Rom ablegen, aber 
Referenzen dazu in's Ram zeigen zu lassen, in der Hoffnung, dass die 
crt0-Fee den Code nach dem Startup rüberkopiert (>RAM at >ROM).
Vielleicht ist da ausversehen irgendein Schalter umgelegt worden, ohne 
dass ich's gemerkt habe. Merkwürdig ist nur, dass der Sprung ins Flash 
geht und nicht ins RAM. Da müsste das Linkerscript (das ja für STM32 
gebaut wurde) schon ziemlich durcheinander geraten sein...
Muss das mal checken, wenn ich zu Hause bin.

Vielen Dank schon mal!

Simon

von Simon H. (simi)


Angehängte Dateien:

Lesenswert?

Grrrrrr, es wird immer merkwürdiger! Schaut Euch mal diesen Screenshot 
an und sagt mir, was das denn soll!?!

Ich habe zweimal einen Aufruf von __init_Data(), und der Lümmel springt 
zweimal wo anders hin (siehe Disassembly)!

Ich kann mir das schlicht nicht mehr erklären! Da kann ich doch machen, 
was ich will, ein Label sollte doch immer die gleiche Adresse haben?

Kann sich jemand von Euch so was auf irgendeine Art erklären?

Übrigens: Weder die erste Adresse noch die zweite stimmt - zumindest 
insofern ist der Linker konsistent! ;-)

von Simon H. (simi)


Lesenswert?

GRRRRR.... Ich tat dem Linker unrecht!

  /* Initialize data and bss */
  __Init_Data();
 8000068:  f240 0395   movw  r3, #149  ; 0x95
 800006c:  f6c0 0300   movt  r3, #2048  ; 0x800
 8000070:  4798        blx  r3
  __Init_Data();
 8000072:  f240 0395   movw  r3, #149  ; 0x95
 8000076:  f6c0 0300   movt  r3, #2048  ; 0x800
 800007a:  4798        blx  r3

.
.
.

void __Init_Data(void) {
 8000094:  b480        push  {r7}

Die Adresse stimmt (bis auf das LSB, das ist für THUMB).


Warum zum Geier aber sagt mir de Debugger was anderes??

von Roland P. (pram)


Lesenswert?

Optimierung?
Da passt dann IMHO nichts mehr zusammen, weil teilweise Fuunktionen 
sogar in falscher Reihenfolge als im C++ Code ausgeführt werden.

Gruß
Roland

von Simon H. (simi)


Lesenswert?

Jup, das hatte ich zuerst. Sah lustig aus, wie der rumhopste! :-)

Aber die habe ich ausgeschaltet.

Merkwürdig ist, dass der Prozi wirklich an die falsche Stelle springt 
(es sei denn, der Debugger lügt mich EXTREM dreist an).

---> List File stimmt. Debugger "sieht" das aktuelle File (den doppelten 
Aufruf von __init_Data(). Im Flash steht tatsächlich ein doppelter 
bx-Befehl, wo er stehen sollte. Aber mit einer anderen Adresse als im 
List-File.

Was also inzwischen klar ist: Im Prozi-Flash steht was, was da nicht 
stehen sollte. Aber nur etwas ganz bischenbischen anderes. Nur die 
Adressen sind falsch....

..... inzwischen fange ich an, zu glauben, dass das Flash durch ist...

von Simon H. (simi)


Lesenswert?

ok, ich sehe das Problem... naja, es ist jetzt zumindest nicht mehr 
soooo merkwürdig.

Meine letzte Aussage stellte sich als falsch heraus. Da ist halt doch 
etwas GANZ anderes im Flash als im Ram. Nämlich "alter" Code. Der wird 
gar nicht neu geflashed. Dann muss ich mal schauen, warum. Auf jeden 
Fall klärt das, warum der Sprünge an Adressen macht, die laut 
Source-File, Linker-Script und Map-File völlig falsch sind.

Nichts für Ungut
Simon

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.