Converting project to use LTO, running into several issues

Asked by JC Wren

I'm converting a project that compiles nicely under 4.9 2015q1 to 5.4 2016q3. Before attempting to use LTO, I've confirmed it compiles and runs.

The first issue is that I had to add -fno-builtins, or I had unresolved references to printf, vfprintf, memcmp, alloc, and several others. I'm somewhat indifferent to whether I use builtins or not, but I'm curious why those would be unresolved references.

The stopping issue for me is that now __clear_cache is unresolved in every .o file in the project. I was going to disassemble the .o file with objdump, but it seems when the -flto is used, that's no longer possible.

I was hoping if there was any insight from someone who has hit this before I try to cook down a minimal test case, etc. The project itself has about 286 .c files, and a couple .S files, although I imagine it shouldn't be take too long to get a minimal test case should I need to.

I'm using 5.4 2016q3 under Windows 7. The target is an STM32L151ZD. -flto is enabled when compiling .c and .S files. I had to add '--plugin liblto_plugin-0.dll' to the 'arm-eabi-none-ar' command (all the .o files go into a .a file). The link step has -flto -fuse-linker-plugin. Everything compiles clean. The dying words from the linker are below.

Any ideas what I'm missing/doing wrong/etc?

C:\cygwin\tmp\ccfP5qhA.ltrans5.ltrans.o: In function `radioConfigureGetToCLI':
C:\cygwin\home\thisuser\am\compare\v2178/project/net/radio.c:1627: undefined reference to `__clear_cache'
C:\cygwin\tmp\ccfP5qhA.ltrans8.ltrans.o: In function `deviceInit':
C:\cygwin\home\thisuser\am\compare\v2178/project/device.c:1881: undefined reference to `__clear_cache'
C:\cygwin\tmp\ccfP5qhA.ltrans9.ltrans.o: In function `netcommSendExpect':
C:\cygwin\home\thisuser\am\compare\v2178/project/net/netcomm.c:962: undefined reference to `__clear_cache'
C:\cygwin\tmp\ccfP5qhA.ltrans12.ltrans.o: In function `uartPutChar':
C:\cygwin\home\thisuser\am\compare\v2178/uart/uart.c:629: undefined reference to `__clear_cache'
C:\cygwin\tmp\ccfP5qhA.ltrans17.ltrans.o: In function `wiredConfigureGetToCLI':
C:\cygwin\home\thisuser\am\compare\v2178/project/net/wired.c:1539: undefined reference to `__clear_cache'
C:\cygwin\tmp\ccfP5qhA.ltrans19.ltrans.o:C:\cygwin\home\thisuser\am\compare\v2178/storage/i2c_eeprom.c:424: more undefined references to `__clear_cache' follow
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile:731: output/project_final.elf] Error 1

Question information

Language:
English Edit question
Status:
Answered
For:
GNU Arm Embedded Toolchain Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Andre Vieira (andre-simoesdiasvieira) said :
#1

Hi JCWren,

Could you post a reduced testcase and a full commandline such that I can reproduce your issue?

For instance on my end the following works fine:

$ cat t.c
#include <stdio.h>

int
main (void)
{
        printf ("Hello World!\n");
        return 0;
}
$ arm-none-eabi-gcc --specs=rdimon.specs -mcpu=cortex-m3 -mthumb t.c

Revision history for this message
JC Wren (jcwren) said :
#2

I'm trying to create a test case, but having some trouble. Here's what I do know. A few of my .o files generate calls to __clear_cache.

From the GCC manual:

— Built-in Function: void __builtin___clear_cache (char *begin, char *end)
This function is used to flush the processor's instruction cache for the region of memory between begin inclusive and end exclusive. Some targets require that the instruction cache be flushed, after modifying memory containing code, in order to obtain deterministic behavior. If the target does not require instruction cache flushes, __builtin___clear_cache has no effect. Otherwise either instructions are emitted in-line to clear the instruction cache or a call to the __clear_cache function in libgcc is made.

I think what's happening is that this is a builtin that doesn't get excluded by -fno-builtin, and it's not a library function. Creating a .lst file from a non-LTO version, we see these lines:

08008150 <__clear_cache>:
 8008150: 4770 bx lr
 8008152: bf00 nop

Out of the 200+ .o files, there's a total of 14 calls to __clear_cache by various functions. I haven't yet figured out what condition causes GCC to emit a __clear_cache call. I thought one cause might be the use of a volatile, but my small test case doesn't cause that to be generated, even with a couple files making external references to it.

I know this isn't as much help as having an actual test case to run, and I'm still working on that, but does this provide any useful information in the mean time? Also, here's the cc, ar, and ld command lines (I omitted the cc lines for all but main.c for brevity):

"/cygdrive/c/Program Files (x86)/GNU Tools ARM Embedded/5.4 2016q3/bin/"arm-none-eabi-gcc -flto -c -Wall -Wextra -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wunused -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-packed-bitfield-compat -Ilib/stm32l1xx/inc -Isystem/stm32l1xx -mcpu=cortex-m3 -mthumb -g -Os -fomit-frame-pointer -D STM32L1XX_HD -D USE_STDPERIPH_DRIVER -D LSE_VALUE=32768 -D HSE_VALUE=12000000 -D SPEED_HSE=12000000 -D SPEED_CPU=32000000 -D SYSCLK_FREQ_72MHz=32000000 -D PREFER_PORTABLE_SNPRINTF -D STM32L151ZDT6 -D _GNU_SOURCE -ffunction-sections -fdata-sections -fno-builtin main.c -o main.o

"/cygdrive/c/Program Files (x86)/GNU Tools ARM Embedded/5.4 2016q3/bin/"arm-none-eabi-ar rc --plugin liblto_plugin-0.dll common/armlib.a main.o extfunc.o system/stm32l1xx/startup_stm32l1xx_hd.o

"/cygdrive/c/Program Files (x86)/GNU Tools ARM Embedded/5.4 2016q3/bin/"arm-none-eabi-gcc -flto -fuse-linker-plugin -Wall -Wextra -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wunused -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-packed-bitfield-compat -Ilib/stm32l1xx/inc -Isystem/stm32l1xx -mcpu=cortex-m3 -mthumb -g -Os -fomit-frame-pointer -D STM32L1XX_HD -D USE_STDPERIPH_DRIVER -D LSE_VALUE=32768 -D HSE_VALUE=12000000 -D SPEED_HSE=12000000 -D SPEED_CPU=32000000 -D SYSCLK_FREQ_72MHz=32000000 -D PREFER_PORTABLE_SNPRINTF -D STM32L151ZDT6 -D _GNU_SOURCE -ffunction-sections -fdata-sections -fno-builtin -Wl,--gc-sections,--discard-none,-Map=output/main.map,--cref,-u,Reset_Handler -T ldscripts/stm32l151zd.ld common/armlib.a "-lc" "-lgcc" common/armlib.a --specs=nano.specs -nostartfiles -o output/main.elf

Revision history for this message
Thomas Preud'homme (thomas-preudhomme) said :
#3

Hi JC,

Could you try without the --gc-sections option?

Best regards,

Thomas

Revision history for this message
JC Wren (jcwren) said :
#4

No difference :(

Revision history for this message
Thomas Preud'homme (thomas-preudhomme) said :
#5

What's strange is that if anything -fno-builtins should make it worse. Without it, GCC is free to emit a sequence of instruction instead of calling a function. __clear_cache is part of libgcc and if it used the linker should include the function. I'm guessing __clear_cache is not part of the LTO sections so the linker does not pick __clear_cache and later when doing the LTO optimization __clear_cache is emitted and an error is given because it's not available.

Sadly we really need a testcase to be able to get more details into what's happening. Please keep trying reducing it if possible. With regards to __clear_cache I'm guessing it would be generated if you try to branch to a volatile memory location. Something along the lines of:

volatile void *ptr;

void
foo (void)
{
  goto **ptr;
}

Best regards.

Revision history for this message
JC Wren (jcwren) said :
#6

How or where should I attach a .zip or .tar file? There's 5 files necessary to build it and fail (two .c, one .S, one .ld, and the Makefile)

Revision history for this message
Thomas Preud'homme (thomas-preudhomme) said :
#7

I believe it's possible to attach a file in bug reports. So either open a bug report and attach it there or push it somewhere else online.

Best regards,

Thomas

Revision history for this message
JC Wren (jcwren) said :
#8
Revision history for this message
JC Wren (jcwren) said :
#9

Any traction on this issue?

Revision history for this message
Thomas Preud'homme (thomas-preudhomme) said :
#10

Yes, this seems more and more like a bug to me. Thanks for the report and all the file to reproduce.

Best regards.

Revision history for this message
Thomas Preud'homme (thomas-preudhomme) said :
#11

Marking the question as answered since it's already being tracked by https://bugs.launchpad.net/gcc-arm-embedded/+bug/1630668

Can you help with this problem?

Provide an answer of your own, or ask JC Wren for more information if necessary.

To post a message you must log in.