Forum: Compiler & IDEs Arm GCC mit Option -flto erzeugt Fehler


von Reiner S. (Gast)


Lesenswert?

Wenn ich die Option -flto einsetze wird folgender Fehler vom Linker 
geworfen:
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'

Es ist ein kurzes Testprogramm in dem keine printf oder scanf Funktionen 
aufgerufen werden. Nur ein GPIO-Pin und CDC wird von von HAL verwendet. 
Wenn ich ohne -flto compeliere läuft es durch.
Ich habe es mit Atollic TrueStudio gcc 6.x und Swstm32 gcc 7.x getestet, 
bei beiden das gleiche Problem.

Danke

: Gesperrt durch Moderator
von Dr. Sommer (Gast)


Lesenswert?

Reiner S. schrieb:
> Wenn ich ohne -flto compeliere läuft es durch.

Dann mach mal ein objdump auf das erstellte ELF und schaue wo malloc 
aufgerufen wird. Vermutlich ist irgendwo in der HAL noch ein printf () 
Aufruf.

von (Gast)


Lesenswert?

soweit ich mich erinnere ist für LTO ein plugin nötig, selbiges teilt 
man ar, ld und co über gcc/g++ mittels
1
-r --plugin /usr/lib/gcc/arm-none-eabi/7.3.1/liblto_plugin.so.0

mit. Pfad je nach Version und Betriebssytem anpassen.

von Reiner S. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Dann mach mal ein objdump auf das erstellte ELF und schaue wo malloc
> aufgerufen wird. Vermutlich ist irgendwo in der HAL noch ein printf ()
> Aufruf.

Ja malloc wird aufgerufen aber ohne -flto wird des Programm übersetzt 
und USB funktioniert. Ist die Reihenfolge der Module beim übersetzen 
wichtig?

von Reiner S. (Gast)


Lesenswert?

Hallo rµ
Ich arbeite unter Windows und es gib eine liblto.dll. Ich gehe aber 
davon aus das der gcc mit der Option -flto die liblto.dll automatisch 
aufruft.

von x^y (Gast)


Lesenswert?

Bist du sicher, dass das Projekt vollständig neugebaut wurde und keine 
alten Objekt Dateien überlebt haben? -flto erzeugt speziell 
instrumentierte Objektdateien. malloc() in MCU Firmware ist ein bißchen 
wie der Papst auf der Reeperbahn. Sollte man unabhängig davon aus dem 
Projekt eliminieren. Ist dir aber sicher bekannt :)

von Reine S. (Gast)


Lesenswert?

x^y schrieb:
> Bist du sicher, dass das Projekt vollständig neugebaut wurde und
> keine
> alten Objekt Dateien überlebt haben? -flto erzeugt speziell
> instrumentierte Objektdateien.
Ich denke schon. Habe aber noch mal alle *.o und *.su Dateien gelöscht.
Leider keine Besserung.

> malloc() in MCU Firmware ist ein bißchen
> wie der Papst auf der Reeperbahn. Sollte man unabhängig davon aus dem
> Projekt eliminieren. Ist dir aber sicher bekannt :)
Bei kleinen 8 Bitern ist schon richtig, aber bei einem STM32F407 sehe 
ich kein Problem sich einen Puffer per malloc zu beschaffen.
Außerdem ist das malloc im USB-Treiber von HAL eingebaut.

von Reine S. (Gast)


Lesenswert?

Habe mir mal die map-Files mit und ohne lto angesehen. Der Fehler mit 
lto
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
Im map-File ist _sbrk nicht zu finden.

Beim compelieren ohne lto findet sich _sbrk im map-File

OTG_FS_IRQHandler
                0x08004014       0x10 Src\stm32f4xx_it.o
                0x08004014                OTG_FS_IRQHandler
 .text._sbrk    0x08004024       0x3c Src\syscalls.o
                0x08004024                _sbrk

und das Programm rennt.

MfG

von Vincent H. (vinci)


Lesenswert?

Markier sbrk mal testweise als "used" via
1
__attribute__((__used__))

von Dr. Sommer (Gast)


Lesenswert?

Bindest du das USB-Zeug (also das welches malloc aufruft) über eine 
statische Library ein?

Dann versuch mal per -Wl,--start-group -lblabla -Wl,--end-group zu 
linken.

von A. B. (Gast)


Lesenswert?

Eventuell hilft ein

__attribute__((used)) void *dummy(void) {
  return _sbrk(0);
}

irgendwo, um den Compler/Linker zu überzeugen, dass _sbrk tatsächlich 
gebraucht wird und nicht wegoptimiert werden darf. Man könnte das 
__attribute__((used)) auch einfach vor die Definition vom _sbrk setzen, 
aber das wäre mit mehr Aufwand verbunden.

von Olaf (Gast)


Lesenswert?

> Bei kleinen 8 Bitern ist schon richtig, aber bei einem STM32F407 sehe
> ich kein Problem sich einen Puffer per malloc zu beschaffen.

Die groesse des Microcontrollers ist vollkommen irrelevant und ausserdem 
auch nur relativ zu deinen Speicheranforderungen.

Du solltest dich aber fragen was macht dein Programm wenn malloc 
zurueckliefert das kein Speicher mehr da ist. Hast du dann eine 
Out-of-Memory BlinkLED? Oder stuerzt dein Programm einmal im Jahr ab?

Olaf

von Dr. Sommer (Gast)


Lesenswert?

Reine S. schrieb:
> Bei kleinen 8 Bitern ist schon richtig, aber bei einem STM32F407 sehe
> ich kein Problem sich einen Puffer per malloc zu beschaffen

Hoffentlich nicht in einer Interrupt-Routine (lief die ST-USB-Library 
nicht ausschließlich in Interrupts...?). Das gibt sonst lustige Race 
Conditions und Delays.

von DPA (Gast)


Lesenswert?

Ich würde von LTO generell abraten. Das zeug macht nur Probleme. Ich hab 
schon schlechte Erfahrungen damit gemacht, z.B. bei Projekten mit weak 
Symbols und ähnlichem.

von Oliver S. (oliverso)


Lesenswert?

Pauschale Urteile sind meistens pauschal falsch.

Oliver

von Reiner S. (Gast)


Lesenswert?

Malloc wird nur beim init aufgerufen und sollte somit kein Problem 
seien.
Die anderen Tips werde ich ausprobieren und mich dann melden.

Danke an alle.

von Reiner S. (Gast)


Lesenswert?

Noch mal Danke.
Cube MX generiert ein Modul syscalls.c in der _sbrk definiert ist.
Ich habe wie von Vincent H. vorgeschlagen __attribute__((_used_)) 
eingefügt und das war die Lösung.
Bleibt die Frage warum zur Höllen der GCC _sbrk mit -flto weg optimiert.

MfG
Reiner

von Dr. Sommer (Gast)


Lesenswert?

Reiner S. schrieb:
> Malloc wird nur beim init aufgerufen und sollte somit kein Problem
> seien.

D.h. die Speicheraufteilung ist gar nicht dynamisch, und du weißt von 
Anfang an wofür wieviel gebraucht  wird? Dann kannst du auch eine 
globale Variable machen. Dadurch sparst du dir den Programmspeicher für 
malloc, und der Linker kann besser den Verbrauch prüfen. Schneller 
starten tut es auch.

Reiner S. schrieb:
> Bleibt die Frage warum zur Höllen der GCC _sbrk mit -flto weg optimiert.

Weil sbrk indirekt über die libc referenziert wird und der Linker das 
nicht auflöst.

von Reiner S. (Gast)


Lesenswert?

Der ganze malloc Kram sitzt in der HAL von STM und das möchte ich nicht 
ändern. Ich denke STM hat sich für malloc entschieden damit es möglichst 
universel ist und mit CubeMX harmoniert. Wider was dazu gelernt mit der 
Libc.
MfG

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Wieder ein weiterer Grund die HAL nicht zu nutzen ;)

von Le X. (lex_91)


Lesenswert?

Mw E. schrieb:
> Wieder ein weiterer Grund die HAL nicht zu nutzen ;)

Genau, weil die Anfänger von STM machen ständig nur so Mist, die haben 
ja keine Ahnung.
Das kriegst du bestimmt schneller selbstgeschrieben hin. Natürlich 
hochwertiger und sicherer.

von fsdf (Gast)


Lesenswert?

Le X. schrieb:
> Genau, weil die Anfänger von STM machen ständig nur so Mist, die haben
> ja keine Ahnung.

Was die ST HAL angeht, so ist sie definitiv stinkender Mist. Sie ist 
ganz nett, um eine Übersicht über die notwendigen Register zu kriegen, 
mehr aber nicht.

Die libopencm3 oder direkt Barebone auf die Register ist deutlich 
aufgeräumter.

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Le X. schrieb:
> Genau, weil die Anfänger von STM machen ständig nur so Mist, die haben
> ja keine Ahnung.
Leider ist es aber so.

Also was ich beim USB Host mir RTOS erlebt habe geht auf keine Kuhaut 
mehr.
(Son USB Host schreibt eben nicht mal eben selber)

Die config structs nutzen meist uint32_t oä statt enums.
Somit funktionieren keine Vorschaufunktionen von IDEs für mögliche 
Werte.
Eine suche über rechtsklick "go to definition of xyz" geht so auch nicht 
und man muss im Headerfile rumscrollen bis mans findet.
Weiterhin kann man so ausversehen falsche Bitmasken reinwerfen ohne, 
dass der Compiler meckert (vertipper).

Netter UART/PLL Bug beim L431 im Zusammenhang mit dem GammelMX:

Im UART wird eine Baudrate falsch gesetzt, weil der APB Takt falsch 
zurückgerehcnet wird.
uint32_t clk = HAL_RCC_GetPCLK2Freq(); // CLK = 31750000 statt 80000000
usartdiv = (uint16_t)(UART_DIV_SAMPLING16(clk, huart->Init.BaudRate));
Dadurch stimmt die Baudrate nicht mehr (div = 276)

Woran liegts?
1
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
2
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
3
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
4
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
5
//RCC_OscInitStruct.PLL.PLLM = 1;                    << wird von CubeMX nicht inited und steht daher auf 0 -> HAL nimmt defaultwert von 2, aber die PLL bekommt 1 im Reg
6
RCC_OscInitStruct.PLL.PLLN = 10;
7
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;
8
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
9
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

Leider muss ich auf Arbeit den Schrott nutzen, aber somit kann ich 
wenigstens Kompromat in meinem Redmine sammeln ;)

Beitrag #7410353 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.