Hallo Leute, nachdem ich im 'Teufelswerk'-Thread einiges ueber den LTO vom GCC erfahren habe, spiele ich mit dem Gedanken, meine Bibliothek zu aendern. Bisher hacke ich grosse *.c-Files mit einem Perl-Script in kleine Stuecke (die Stuecke markiere ich mit speziellen Kommentaren im c-File) und pack die *.o-Stueckchen in eine lib*.a . Das kann ich mir dank LTO ja dann sparen. Soweit ist noch alles gut. ABER: Mit dem Bewusstsein, dass ein *.o die Einheit ist ueber die beim Linken entschieden wird ob sie ins fertige Programm kommt oder nicht habe ich auch folgenden Kniff benutzt: Manche Bibliotheks-*.c-Files enthalten eine normale Funktion (moduleXyInit(...)), die im *.h ebenfalls auftaucht und im Hauptprogramm gerufen wird und zus"atzlich noch einen Interrupt-Handler B. Dieser Interrupt-Handler B wird sozusagen vom Linker unbeabsichtigt (aber von mir beabsichtigt!) ins fertige Programm gelinkt und ersetzt dann eine weak-Reference auf einen dummy-Interrupt-Handler A. Ist das noch sauberes Programmieren oder schon fragwuerdige Praktik? Macht der LTO solche Sachen dann auch noch richtig? Der Interrupt-Handler B ist ja streng genommen nicht notwendig und koennte einfach wegoptimiert werden, weil Handler A schon vorhanden? Oder wie macht ihr das mit dem automatischen Installieren von ISR-Handlern aus Bibliotheksmodulen in der ISR-Vector-Tabelle (im FLASH)?
Marc P. schrieb: > Hallo Leute,nachdem ich im 'Teufelswerk'-Thread einiges ueber den LTO > vom GCC erfahren habe, spiele ich mit dem Gedanken, meine Bibliothek zu > aendern. Bisher hacke ich grosse *.c-Files mit einem Perl-Script in > kleine Stuecke (die Stuecke markiere ich mit speziellen Kommentaren im > c-File) und pack die *.o-Stueckchen in eine lib*.a . Das kann ich mir > dank LTO ja dann sparen. Soweit ist noch alles gut.ABER:Mit dem > Bewusstsein, dass ein *.o die Einheit ist ueber die beim Linken > entschieden wird ob sie ins fertige Programm kommt oder nicht habe ich > auch folgenden Kniff benutzt: Manche Bibliotheks-*.c-Files enthalten > eine normale Funktion (moduleXyInit(...)), die im *.h ebenfalls > auftaucht und im Hauptprogramm gerufen wird und zus"atzlich noch einen > Interrupt-Handler B. Dieser Interrupt-Handler B wird sozusagen vom > Linker unbeabsichtigt (aber von mir beabsichtigt!) ins fertige Programm > gelinkt und ersetzt dann eine weak-Reference auf einen > dummy-Interrupt-Handler A. Ist das noch sauberes Programmieren oder > schon fragwuerdige Praktik?Macht der LTO solche Sachen dann auch noch > richtig? Der Interrupt-Handler B ist ja streng genommen nicht notwendig > und koennte einfach wegoptimiert werden, weil Handler A schon > vorhanden?Oder wie macht ihr das mit dem automatischen Installieren von > ISR-Handlern aus Bibliotheksmodulen in der ISR-Vector-Tabelle (im > FLASH)? Erstmal, für das was du vorhast brauchst du keine LTO. Da ist eher -ffunction-sections und -fdata-sections das Mittel der Wahl. Dadurch sparst du dir dein Skripgesteuertes Zerhacken und deine Lib.a hat auch nur ein Objekt-file. Aber zu deiner Frage: ja, bei LTO kann es dir passieren dass dir eine ISR flöten geht, da diese ja nicht direkt benutzt wird sondern von der Hardware angesprungen wird. Im Zweifel das Listing kontrollieren! Der gcc kennt allerdings ein Attribut um Funktionen zu markieren die immer dazugelinkt werden sollen. always_use oder so ähnlich. Google oder das gcc Manual helfen dir weiter. Es schadet nicht, damit deine ISRs zu markieren.
mit -ffunction-sections kann das was nach dem ABER oben steht nicht mehr funktionieren, das die ISR B dann gar nicht mehr als Kandidat in Frage kommt. Nicht so gut... Daher die Hoffnung mit dem LTO. Haro schrieb: > Aber zu deiner Frage: ja, bei LTO kann es dir passieren dass dir eine > ISR flöten geht, da diese ja nicht direkt benutzt wird sondern von der > Hardware angesprungen wird. Aber von meinen Assembler-Sachen (Startup Code) laesst der LTO doch hoffentlich die Finger, oder?
Haro schrieb: > Aber zu deiner Frage: ja, bei LTO kann es dir passieren dass dir eine > ISR flöten geht, da diese ja nicht direkt benutzt wird sondern von der > Hardware angesprungen wird. Käse. Wenn das ISR Makro aus der AVR-Libc verwendet wird, dann sind alle ISR-Routinen mit __attribute__((_used_)) markiert, d.h. der Compilerwird sie nicht wegwerfen weil sie unbenutzt sind / erscheinen. Und der Linker kann sie nicht wegwerfen, weil sie vom Startup-Code (bzw. Vector-Tabelle) referenziert widd.
Johann L. schrieb: > Und der Linker kann sie nicht wegwerfen, weil sie vom Startup-Code (bzw. > Vector-Tabelle) referenziert widd. Und was hindert ihn daran, die auch noch mit wegzuwerfen? Dass sie auch mit __attribute__((used)) markiert sind... ;-)
Dr. Sommer schrieb: > Johann L. schrieb: >> Und der Linker kann sie nicht wegwerfen, weil sie vom Startup-Code (bzw. >> Vector-Tabelle) referenziert wird. > Und was hindert ihn daran, die auch noch mit wegzuwerfen? Dass sie > auch mit __attribute__((used)) markiert sind... ;-) Nö :-) Die Vector-Tabelle ist im Linker-Description als KEEP markiert:
1 | .text : |
2 | { |
3 | *(.vectors) |
4 | KEEP(*(.vectors)) |
attribute ist ein Konzept des Compilers, bereits im Assemblercode (.s) ist nichts mehr davon zu sehen -- außer eben den Effekt, daß die entsprechende Funktion nicht wegoptimiert ist. D.h. im object-Code gibt's nix, was einem "used" entspricht. Neben KEEP gibt's noch andere Mechanismen wie den Entry Point.
Danke fuer die Infos! Jetzt wird einiges klarer - endlich weiss ich wozu das KEEP da ist :) Ich denke ich versuche folgenden Weg: Linker-Script schuetzt wie von Johann gezeigt mit KEEP die VectorTabelle. Der ISR default handler A muss dann ausserhalb der vectorTabellen-Section sein, dadurch also prinzipiell 'faellig' wenn seine weak reference durch eine starke Referenze B ersetzt sind => LTO kassiert default handler A dann, aber auch nur dann. In der Lib fasse ich eine (beliebigen Namens) init-Funktion in einer Section (.text) (= ein C-File) mit der zum Modul gehoerenden ISR B zusammen und markiere sie mit __attribute__((used)). => B ueberschreibt A => LTO eliminiert A. Fein! Das mit den *.c - Schnipseln geht mir naemlich langsam auf den Zeiger: es sind mittlerweile knapp unter 500 und da braucht gcc dann schon ein wenig Zeit. PS: ist uebrigens fuer ARM7/M0/M3 gedacht, aber das macht ja keinen prinzipiellen Unterschied.
Hab gestern abend den ersten Versuch gestartet das umzusetzen. Ein LED-blink-Programm hat dann auch funktioniert und war klein :) Target: LPC812 (Cortex-M0+, keine Divisionsbefehle!). Die ISR ist korrekt 'gelinkt' worden. Aber sobald ich eine Ausgaberoutine verwende, die Division (durch 10) verwendet: Krawummm! Muss ich bei libgcc bzw. deren Ersatz etwas besonderes beachten bei Verwendung von LTO?
Marc P. schrieb: > Muss ich bei libgcc bzw. deren Ersatz etwas besonderes beachten bei > Verwendung von LTO? Sorry meine Schuld ! Habe im Linker-Script text.unlikely-Sections verschlampert. Jetzt tut's! Bilanz (gcc-4.8.1): ca. 1500 bytes statt (bisher) ca. 1800 bytes fuer Temperaturmessung mit DS75, Festkomma-Zahlen- und Textausgaben, und power-down. Das lohnt sich halt besonders bei den ganz kleinen Microcontrollern, z.B. LPC810 mit nur 4k FLASH :-)
:
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.