Forum: Compiler & IDEs Unbenutzten Code durch GCC entfernen lassen


von Detlef _. (detlef_a)


Lesenswert?

Liebe GCC-Spezialisten,

ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den 
unbenutzten Code durch den GCC rauschmeißen lassen. Dazu nehme ich nach 
WEB-Anleitung den Compilerswitch

CFLAGS += -ffunction-sections

hinzu, der mir die functions jeweils in eine eigene Section packt. Das 
klappt, denn wenn ich das ohne Rauschmeissen zusammenlinke gehts.

Dann sage ich dem Linker mit

LDFLAGS = -Wl,-Map=$(TARGET).map,-gc-sections,--cref
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)

dass er die unbenutzten Sections rausschmeissen soll.
Das scheint auch zu klappen, das .elf File ist kleiner.
Der Umbau des .elf Files zum ladbaren .hex file gelingt aber nicht, das 
.hex file wird dann sehr kurz, 13 Byte.

Die commandline lautet dazu:
avr-objcopy -O ihex -R .eeprom main.elf main.hex

Was mache ich denn da falsch?

THX
Cheers
Detlef

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Zu wenig Information, daher nur Gestocher:
text.* oder text* im Linker-Skript? Entry im Linker-Skript gesetzt? Nur 
von der Hardware "direkt" aufgerufenen Code (Interrupt-Handler und/oder 
Vector-Tabelle(n)) per KEEP im Linker-Skript vor unused-code-removal 
geschützt?

Minimale Beispielanwendung mit allen notwendigen Dateien und 
Beschreibung, wie das Problem nachzuvollziehen ist erzeugen, 
zusammenpacken und als Attachment hier einstellen.

von OlliW (Gast)


Lesenswert?

Hallo,

die Antwort auf die Frage wie man den avr-gcc dazu bringt unbenutzte 
Funktionen rauszuschmeissen würde mich auch interessieren.

Suchen - und ich bin eigentlich ein fleissiger Sucher - hat mich bisher 
nicht weiter gebracht (sorry). Ich verstehe dass auch nicht so ganz, 
warum macht ein optimierender Compiler die einfachste Optimierung nicht 
automatisch selber?

Ciao,
  Olli


PS: Ich gebe zu ein Windowsuser zu sein, Dinge wie Linkerskripte oder 
make-Files lösen bei mir keine Begeisterung aus. Ich benutze WinAvr + 
AVR-Studio. Beispiel C-Program ist einfach: Standard includes, zwei 
Funktionen definieren, im main nur eine davon aufrufen. Das .lst File 
zeigt Code für beide Funktionen an, und das .hex File ist auch grösser 
als wenn man die unbenutze Funktion per Hand auskommentiert.

von Karl H. (kbuchegg)


Lesenswert?

OlliW schrieb:

> Suchen - und ich bin eigentlich ein fleissiger Sucher - hat mich bisher
> nicht weiter gebracht (sorry). Ich verstehe dass auch nicht so ganz,
> warum macht ein optimierender Compiler die einfachste Optimierung nicht
> automatisch selber?

Weil das keine Sache des Compilers ist, sondern des Linkers.

Der Compiler kennt nur im Ausnahmefall das komplette Programm. Aber 
abgesehen davon, sieht er immer nur Bruchstücke. Wenn er eine Funktion 
vorgeworfen bekommt, weiß er nicht, wo diese Funktion überall verwendet 
wird, es könnte ja auch in einem ganz anderen *.c ein Aufruf dieser 
Funktion stehen.

von Peter (Gast)


Lesenswert?

Das Beste ist immer noch, wenn man seinen Code selber von "Hand" 
ausmistet und den nicht benötigten Müll rauswirft! Nur so bleiben 
Projekte überschaubar bzw. man behält als Programmierer den Überblick!

Ausnahme: Wenn man seine eigene Funktionssammlung als "Lib" übersetzt, 
pickt sich der Linker nur die wirklich benötigten Funktionen raus!

von OlliW (Gast)


Lesenswert?

>Weil das keine Sache des Compilers ist, sondern des Linkers.

OK, da war ich schlampig, also neuer Versuch: Ich verstehe dass auch 
nicht so ganz, warum wird ein optimierender Compiler mit einem Linker 
verpackt der die einfachste Optimierung nicht automatisch selber macht? 
:-)

@Peter: das ist Ansichtssache. Ich programmiere sonst mit VisualC und 
finde es sehr angenehm dass der mir meinen "Müll" rauswirft :-)

Olli

von Peter D. (peda)


Lesenswert?

Müll rauswerfen und total optimieren:

--combine
-fwhole-program


Peter

von Thomas (Gast)


Lesenswert?

>ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den
>unbenutzten Code durch den GCC rauschmeißen lassen.
Unbenutzten Code schmeißt man nicht rau, man schreibt ihn erst gar nicht 
erst rein. :)

von Simon K. (simon) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Müll rauswerfen und total optimieren:
>
> --combine
> -fwhole-program
>
>
> Peter

Ja, aber vergiss nicht zu sagen, dass dann alle .c Dateien in einem 
Compileraufruf kompiliert werden müssen.

von Karl H. (kbuchegg)


Lesenswert?

Thomas schrieb:
>>ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den
>>unbenutzten Code durch den GCC rauschmeißen lassen.
> Unbenutzten Code schmeißt man nicht raus, man schreibt ihn erst gar
> nicht erst rein. :)

:-)
Wenn man Code-Baugruppen nicht in Form einer Library benutzt, ist es 
unausweichlich
entweder Funktionen zu haben, die nie benutzt werden
oder den Code mit #ifdef zu spicken, so dass sich der Benutzer aussuchen 
kann, was davon mitcompiliert wird und was nicht.
oder sonst irgendeinen Compile/Linker spezifischen Hack gibt, mit dem 
man das Problem lösen kann.

Ein reiner C-Linker kann noch nicht aufgerufene Funktionen detektieren 
und rausschmeissen, weil es auf jeden Fall eine Referenz auf die 
Funktion irgendwo geben muss. Für C++ Kombi-Linker ist das allerdings 
schwieriger bis unmöglich (Stichwort: virtuelle Funktionen).

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

OlliW schrieb:
>...
> PS: Ich gebe zu ein Windowsuser zu sein, Dinge wie Linkerskripte oder
> make-Files lösen bei mir keine Begeisterung aus. Ich benutze WinAvr +
> AVR-Studio. Beispiel C-Program ist einfach: Standard includes, zwei
> Funktionen definieren, im main nur eine davon aufrufen. Das .lst File
> zeigt Code für beide Funktionen an, und das .hex File ist auch grösser
> als wenn man die unbenutze Funktion per Hand auskommentiert.

Dann halt das AVR-Studio Projekt mit allen Dateien zusammenpacken und 
hier anhängen. Das von AVR-Studio erzeugte makefile drin lassen (per 
default im UVZ default, dann können auch nicht-MS-Windows nutzer 
"mitraten"). Zumindest mit neueren gcc aus neueren WinAVR keine Probleme 
mit function-sections/gc-section gehabt, auch in Kombination mit 
AVR-Studio.

von Detlef _. (detlef_a)


Lesenswert?

Mit function-sections/gc-section funktioniert das jetzt. War auch schon 
mal in Beitrag "AVR-GCC Kompiliert nicht benutzte Funktionen mit ein" breit dargestellt, 
hab ich erst später gesehen. Problem war Version des gcc, ich war bei 
3.4 ;-(  , mit dem neuen gings.

>>--combine
>>-fwhole-program
Da muß man jedesmal alles compilieren ?! Das kann dauern.

>>ich erstelle ein Programm in C mit GCC und möchte jetzt gerne den
>>unbenutzten Code durch den GCC rauschmeißen lassen.
>Unbenutzten Code schmeißt man nicht rau, man schreibt ihn erst gar nicht
>erst rein. :)
Super Idee, wäre ich nicht drauf gekommen, es ist immer eine 
Bereicherung, wenn ein erfahrener Entwickler so helfen kann.


THX2ALL
Cheers
Detlef

von OlliW (Gast)


Lesenswert?

ha, jetzt habe ich extra ein Beispiel zusammengestellt und schon gibt es 
die Lösung... wenn das nur immer so ginge das alleine die Möglichkeit 
dass ein Beispiel gepostet wird ausreicht um zu einer Lösung zu 
kommen... ist ja fast quantenmechanisch... ne, echt SUPER, Danke Martin 
und Detlef!!

Und bei meinen Beispiel werden es statt 568 (alle Funktionen) und 216 
bytes (nur die benutzte Funktion) mit dieser Lösung am Ende sogar nur 96 
bytes (egal mit oder ohne unbenutze Funktionen)!

Olli

PS: eigentlich gehört soetwas doch in ein gcc-Tutorial mit und GANZ oben 
rein...

PSS: und warum macht der avr-gcc das jetzt nochmal nicht automatisch von 
selbst? ne, Scherz... echt cool :-)

von Oliver (Gast)


Lesenswert?

>Und bei meinen Beispiel werden es statt 568 (alle Funktionen) und 216
>bytes (nur die benutzte Funktion) mit dieser Lösung am Ende sogar nur 96
>bytes (egal mit oder ohne unbenutze Funktionen)!

Ob das Programm jetzt aber noch das tut, was es soll?

Und auf die Gefahr hin, etwas zu wiederholen:

>Unbenutzten Code schmeißt man nicht rau, man schreibt ihn erst gar nicht
>erst rein. :)

Funktionssammlungen, bei denen man nicht genau weiß, was davon alles 
benutzt wird, packt man halt in eine lib. Wurde die richtig gebaut, holt 
sich der linker daraus nur das, was benötigt wird. Ganz automatisch, 
ohne zusätzliche Optionen.

Oliver

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

Oliver schrieb:
> Funktionssammlungen, bei denen man nicht genau weiß, was davon alles
> benutzt wird, packt man halt in eine lib. Wurde die richtig gebaut, holt
> sich der linker daraus nur das, was benötigt wird. Ganz automatisch,
> ohne zusätzliche Optionen.

Da eine library aber auch nur eine Dateisammlung ist, hast Du genau
das selbe Problem. Der Compiler erzeugt ELF sections für Code und
Daten. Alle Funktionen (Code) einer compilation unit landen in der
selben ELF section.  Der Linker kann eine section nun einbinden oder
weglassen. Existiert auch nur eine Referenz auf eine einzige Funktion
in dieser section, dann muss diese komplett in das image übernommen
werden.

Um das zu vermeiden, kannst Du den Compiler anweisen, jede Funktion in
seine eigene ELF section zu legen (siehe weiter oben im
Thread). Nachteil: Einige Optimierungen können vom Compiler nicht mehr
durchgeführt werden. Außerdem vergrößert sich die Menge der
Verwaltungsdaten (section table) im ELF image möglicherweise
erheblich, was aber bei MCU Anwendungen ohne ELF loader nicht so eine
große Rolle spielt.

Gruß
Marcus
http://www.doulos.com/arm/

von Oliver (Gast)


Lesenswert?

>Alle Funktionen (Code) einer compilation unit landen in der
>selben ELF section.

Richtig. Daher mein Zusatz:
>Wurde die richtig gebaut,...

Eine lib sollte man natürlich aus mehreren sinnvoll zusammengestellten 
compilation units zusammenbasteln.

Oliver

von A. W. (uracolix)


Lesenswert?

> Eine lib sollte man natürlich aus mehreren sinnvoll zusammengestellten
> compilation units zusammenbasteln.

Beim Linken von strukturierten Libraries bin ich bisher auch
auf keinerlei Probleme "ala jetzt geht das Programm nicht mehr" 
gestossen.
D.h. alle Funktionen die sich bedingen in ein gemeinsames C-File packen,
wenn es zu unübersichtlich wird, dann die Funktionen vereinzeln. Das 
ganze als Library zusammenfassen und zum Main-Programm Linken. Das 
funktioniert soweit ich weiss auch beim IAR. Vorteil ist, es sind keine 
abenteuerlichen Compilerschalter im Spiel und man kann damit auch prima 
Default-Callback-Funktionen handhaben. Wenn der Nutzer sie definiert 
hat, dann wird das Object-File aus der Library gar nicht erst gelinkt.

von Marcus H. (mharnisch) Benutzerseite


Lesenswert?

@Oliver

Oliver schrieb:
> Richtig. Daher mein Zusatz:
>>Wurde die richtig gebaut,...

Peter schrieb:
> Ausnahme: Wenn man seine eigene Funktionssammlung als "Lib" übersetzt,
> pickt sich der Linker nur die wirklich benötigten Funktionen raus!

Es konnte beim Leser der Eindruck entstehen, dass der Linker eine 
(statische) Library grundsätzlich anders behandelt als einzelne Objekte.
Wir wissen, das das nicht der Fall ist. Ich hätte also eher Peter 
antworten sollen, als Dir.

Gruß
Marcus
http://www.doulos.com/arm/

von maxim (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Müll rauswerfen und total optimieren:
>
> --combine
> -fwhole-program

Simon K. schrieb:
> Ja, aber vergiss nicht zu sagen, dass dann alle .c Dateien in einem
> Compileraufruf kompiliert werden müssen.

Ich möchte das Thema hier noch einmal aufnehmen. Trotz "compile all" 
erhalte ich dutzende Fehlermeldungen undefined reference to function...

Hat jemand einen Tip woran das liegen kann. Ich nutze WinAVR-20080610 
und das AVR Studio (dort habe ich auch die Compileroptionen hinzugefügt)

von Stefan E. (sternst)


Lesenswert?

maxim schrieb:
> Hat jemand einen Tip woran das liegen kann.

Daran, dass du dich nicht an das hier hältst:
> alle .c Dateien in einem
> Compileraufruf kompiliert werden müssen.

Oder benutzt du etwa ein eigenes Makefile?

von maxim (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Daran, dass du dich nicht an das hier hältst:
>> alle .c Dateien in einem
>> Compileraufruf kompiliert werden müssen.

maxim schrieb:
> Trotz "compile all"
> erhalte ich dutzende Fehlermeldungen undefined reference to function...

Ich gehe davon aus, dass mit compile all diese getan wird. Wenn nicht, 
dann sagt mir bitte was ich sonst machen muss

von Stefan E. (sternst)


Lesenswert?

maxim schrieb:

> Ich gehe davon aus, dass mit compile all diese getan wird.

Damit wird vielleicht alles übersetzt, aber nicht mit einem 
Compileraufruf, sondern mit mehreren separaten Aufrufen.

> Wenn nicht, dann sagt mir bitte was ich sonst machen muss

Eigenes Makefile verwenden.

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.