Re: Symbol resolution differs when building with LTO compared to building without

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



on 2020/6/16 上午10:56, Alice Wang via Gcc-help wrote:
> Hi,
> 
> I've come across some unexpected behavior and I'd appreciate your input on
> the issue. I have an example project below that reproduces the issue. In
> short, when building the project without LTO, a function will resolve to my
> expected version, but when building with LTO, the symbol is resolved to a
> different definition that I do not want.
> 
> Specifically, when building without LTO (which results in the behavior I
> want), the final binary will pull in the definition of `_write` from my
> custom static library that is listed first in the library list. With LTO
> enabled (the bad case), the final binary will pull in the definition of
> `_write` from libnosys, which comes later in the list of static libraries.
> 
> The output of my test project is pasted below. `make` builds without LTO
> and dumping the resulting binary shows that `_write` is my stub
> implementation. `LTO=1 make` builds with LTO enabled, and dumping the
> resulting binary shows the implementation comes from libnosys.
> 
> How can I enable LTO in my build while providing custom definitions for
> library calls (like _write)?
> 
> ~/D/lto_test ❯❯❯ make
> 
> Final binary:
> 00008ae0 <_write>:
>     8ae0: 4610       mov r0, r2
>     8ae2: 4770       bx lr
> 
> ~/D/lto_test ❯❯❯ make clean
> ~/D/lto_test ❯❯❯ LTO=1 make
> 
> Final binary:
> 00008b50 <_write>:
>     8b50: 4b02       ldr r3, [pc, #8] ; (8b5c <_write+0xc>)
>     8b52: 2258       movs r2, #88 ; 0x58
>     8b54: 601a       str r2, [r3, #0]
>     8b56: f04f 30ff mov.w r0, #4294967295 ; 0xffffffff
>     8b5a: 4770       bx lr
>     8b5c: 00018c84 .word 0x00018c84
> 
> ------------------------------------------------
> 
> Toolchain version:
> ARM 9-2020-q2-update (based on the 9 series)
> 
> Repro steps:
> make
> make clean
> LTO=1 make
> 
> Repro project:
> 
> main.c
> ```
> #include <stdint.h>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> 
> int main(int argc, char *argv[]) {
>     printf("Hello.\n");
>     return 0;
> }
> ```
> 
> write.c
> ```
> #include  <unistd.h>
> 
> ssize_t  _write (int      fd,
>                  void    *p_buf,
>                  size_t   cnt)
> {
>     return cnt;
> }
> ```
> 
> Makefile
> Note: You'll have to change the path to point to your local installation of
> the ARM 2020 Q2 toolchain.
> ```
> TOOLCHAIN=<YOUR_PATH_TO_TOOLCHAIN>
> LTO_PLUGIN=$(TOOLCHAIN)/lib/gcc/arm-none-eabi/9.3.1/liblto_plugin.so
> 
> CC=$(TOOLCHAIN)/bin/arm-none-eabi-gcc
> AR=$(TOOLCHAIN)/bin/arm-none-eabi-ar
> DUMP=$(TOOLCHAIN)/bin/arm-none-eabi-objdump
> NM=$(TOOLCHAIN)/bin/arm-none-eabi-gcc-nm
> 
> FLAGS=-g -Os -mthumb -mcpu=cortex-m4 -ffunction-sections -fdata-sections
> --specs=nano.specs --specs=nosys.specs
> ifeq ($(LTO),1)
> FLAGS+=-flto -ffat-lto-objects
> endif
> 
> 
> .PHONY: dump
> dump: main.elf _my_write.o
> @echo "\n======================== Dump ========================"
> @$(NM) -nS _my_write.o
> @echo "\n==================== Final binary ===================="
> @$(DUMP) -d $< | grep "<_write>:" -A 6
> @echo "\n====================== _my_write.o ======================"
> @$(DUMP) -d $(word 2,$^) | grep "<_write>:" -A 6
> @echo "\n======================= libnosys ========================"
> @$(DUMP) -d $(TOOLCHAIN)/arm-none-eabi/lib/thumb/v7e-m/nofp/libnosys.a |
> grep "<_write>:" -A 6
> 
> main.elf: main.a _my_write.a
> @$(CC) $(FLAGS)  -fuse-linker-plugin -fno-common -Wl,-Map=output.map
> -Wl,--gc-sections -o $@ -Wl,--start-group $^ -lc -Wl,--end-group
> 
> %.a: %.o
> @$(AR) --plugin $(LTO_PLUGIN) -rcs $@ $<
> 
> _my_write.o: ./write.c Makefile
> @$(CC) $(FLAGS) -c $< -o $@
> 
> main.o: main.c Makefile
> @$(CC) $(FLAGS) -c $< -o $@
> 
> .PHONY: clean
> clean:
> @rm -rf _write.a main.a main.elf *.res *.out *.o *.s *.map *.dump *.a
> ```
> 
> Once again, any insight would be greatly appreciated. My goal is to enable
> LTO in my project while being able to provide custom definitions of
> specific standard library calls.
> 
> Thanks in advance.
> 
> From,
> AW
> 

Hi Alice,

This symptom made me recall one PR https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91287

Sorry that I don't have the environment for reproduction locally.

Do you mind to try each of below:
  1) Don't use linker-plugin, use -fno-use-linker-plugin explicitly.
  2) Use shared library instead of static library for _write library.
  3) -Wl,--whole-archive -l<your_static_write_library> -Wl,--no-whole-archive
  
HTH.

BR,
Kewen



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux