Forum: Compiler & IDEs gcc Problem mit wrap und lto


von Johannes S. (Gast)


Lesenswert?

Es scheint ein Problem mit Wrapperfunktionen und der LTO zu geben:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88643

Kennt hier jemand einen Workaround? Mit Bugzilla kenne ich mit nicht 
aus, wann könnte sowas gefixt werden? Der Fehler ist für 9.0 gemeldet, 
aktuell gibt es 9.2.1, da sehe ich das Problem immer noch.

von Oliver S. (oliverso)


Lesenswert?

Johannes S. schrieb:
> Kennt hier jemand einen Workaround?

Steht doch da drin : nimm clang. Damit gehts.

Oliver

von Johannes S. (Gast)


Lesenswert?

der Compiler ist vorgegeben und nicht so einfach auszutauschen (Mbed), 
da stehen Aufwand und Nutzen in keinem guten Verhältnis.

von DPA (Gast)


Lesenswert?

Genau wegen solchen Problemen verwende ich generell kein LTO.

In manchen Situationen könnte man ansonsten das weak attribut verwenden.

foo.h:
1
int cook(void);

bar.c:
1
#include "foo.h"
2
__attribute__((weak)) int cook(void){ return -1; }

foo.c:
1
#include "foo.h"
2
// Strong symbol, überschreibt das weak symbol cook
3
int cook(void){ return 0; }

main.c:
1
#include "foo.h"
2
int main(){
3
  if (cook () == -1)
4
    __builtin_abort ();
5
}

von Oliver S. (oliverso)


Lesenswert?

Johannes S. schrieb:
> der Compiler ist vorgegeben und nicht so einfach auszutauschen (Mbed),
> da stehen Aufwand und Nutzen in keinem guten Verhältnis.

Je nun, wer hat denn dann gcc 9 für euer Projekt freigegeben? Wobei gcc 
8.3.1 das Problem auch schon hat.

Oliver

von Johannes S. (Gast)


Lesenswert?

das ist nicht mein Project, Mbed ist ARM. Die unterstüzen schon drei 
toolchains: ARMCC, GCC und IAR. Als OS geht das sehr in die Tiefe und 
schon für die drei Compiler sind viele Fallunterscheidungen nötig.
LTO funktioniert da schon, nur mit den neuen wrappern nicht zusammen. An 
anderen Stellen wurden da schon Workarounds gebaut, für das 
printf/vsnprintf hat das aber noch nicht geklappt. Auch mit WEAK gibts 
die gleiche Mecker.
https://github.com/ARMmbed/mbed-os/issues/12542
Mbed5 ist massig gewachsen, mit bare-metal und LTO passt es jetzt wieder 
in kleine Controller. Dazu gibt es jetzt noch ein skalierbares printf, 
nur alles zusammen geht (noch) nicht.

von DPA (Gast)


Lesenswert?

Johannes S. schrieb:
> Auch mit WEAK gibts die gleiche Mecker.

Bei mir hat's funktioniert, aber mit dem älteren gcc 5.4.0 (der wrap bug 
war bei dem auch da). Hast du es mit dem Beispielcode oben probiert?

von DPA (Gast)


Lesenswert?

Ansonsten, eventuell kannst du es mit einem Macro ersetzen?
1
void foo_a(int x);
2
void foo_b(int x);
3
4
#ifndef ALT_FOO
5
#define foo(...) foo_a(__VA_ARGS__)
6
#else
7
#define foo(...) foo_ ## ALT_FOO(__VA_ARGS__)
8
#endif
1
gcc -DALT_FOO=b

von Johannes S. (Gast)


Lesenswert?

sieht irgendwie kompliziert aus, es soll ja eine Funktion aus der c-lib 
überschrieben werden. Die ist nicht weak definiert und nachträglich geht 
das auch nicht, dafür wird ja das __wrap_printf anstelle von printf 
gelinkt.

z.B:
https://github.com/ARMmbed/mbed-os/blob/c2c6d251fd6d6d7f5f8d5a920b3ad6ce4df0f8ba/platform/source/minimal-printf/mbed_printf_wrapper.c#L33-L41

von DPA (Gast)


Lesenswert?

Johannes S. schrieb:
> es soll ja eine Funktion aus der c-lib
> überschrieben werden.

Ach so. Eventuell kann man da mit der #include_next extension was 
machen:

stdio.h
1
#ifndef MYSTDIO_H
2
#define MYSTDIO_H
3
4
#define printf(...) my_printf(__VA_ARGS__)
5
#define puts(...)   my_puts(__VA_ARGS__)
6
// ...
7
8
#include_next "stdio.h"
9
10
#endif

Wenn man den include path so einrichtet, dass die eigene stdio.h zuerst 
gefunden wird, müsste das dann eigentlich alles auf die eigene umleiten. 
Es sei denn, diese sind bereits macros, dann müsste man die dann nach 
dem #include_next undefinen.

von Johannes S. (Gast)


Lesenswert?

DPA schrieb:
> Ach so. Eventuell kann man da mit der #include_next extension was
> machen:

Danke für deine Ideen und Tipps.
Mit der include Reihenfolge wird es auch schwierig, die wird vom 
Buildsystem zusammengesucht. Könnte man beeinflussen, ist aber sehr 
aufwändig.
Das printf und die Varianten werden ja auch von anderen units benutzt, 
das ist das grössere Problem. Durch die Wrapper beim Linken erwischt man 
automatisch alle units die diese Funktionen benutzen und lenkt alle auf 
die wrapper um. Wenn in dem ganzen Programm auch nur einer die org stdio 
benutzt hätte man den Code beider Funktionen und genau das will man mit 
der Option ja nicht.

Der ARMC6 benutzt clang, mal sehen ob ich das damit testen kann. Den 
habe ich aber nur in der Form vom MbedStudio, und da ist vieles fix 
vorkonfiguriert und der lässt sich nicht aus der cmd starten.
Beim gcc gibt es die Linkeroption -fuse-ld=lld um clang als Linker zu 
benutzen, das hat auch nicht geklappt. Clang habe ich installiert und im 
Suchpfad, lld kann ich starten. Braucht man da eine Crosscompiler 
Version für ARM?

Dann habe ich noch die -u Option zum 'undefine Symbol' probiert. So wird 
z.B. auch main undefined und so der Linker gezwungen die zu suchen. 
Klappt mit -u printf aber auch nicht.

Wenn es nicht geht dann auf den nächsten gcc warten :) Das LTO scheint 
sehr komplex zu sein, da hatte ich vorher auch schon viel mit 
rumprobiert und viele Fehler bekommen.

Edit:
mit -u klappt es doch, es wurde __wrap_vsnprintf angemeckert und ich 
hatte die falsche Funktion angegeben. Irgendwann sollte man Pause 
machen...
Mit "-u main -u printf -u vsnprintf" linkt es, jetzt müsste ich mal die 
Codegrössen vergleichen.
ok, es compiliert, aber der Code mit -lto ist grösser, das printf ist da 
noch aus lib_a_nano drin. Also vertragen sich wrap und lto nicht 
wirklich.

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.