This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Using of arm-none-eabi-ar leads to broken binary

Hello!

I use arm-none-eabi to compile my STM32 project. I want to link my project files to an archive, e.g. libexample.a, to allow link with other objects, e.g. example.o. The libexample.a contains weak symbol replaced by example.o and example.o uses functions from libexample.a.

Now I face the following problem: When I create libexample.a and then link libexample.a with example.o, the resulting elf/bin is malfunction.

When I take example.o and link it directly with .o files used to crate libexample.a, the resulting elf/bin is OK.

Compile flags are equal.

The further investigation showed, that:

  • the bin/elf produced by example.a+example.o link process is smaller than when I take example.o+.o files used to create example.a file
  • the example.a contains all .o files

The Makefile snippet is below:

libexample.a: $(OBJS)
        @echo Creating static library $@
        $(AR) rcs $@ $(OBJS)

ofiles:
        @echo Compiling
        @arm-none-eabi-gcc -c $(CFLAGS) $(INCLUDE) example.c -o example.o
        @echo "Linking (creating .elf)"
        @arm-none-eabi-gcc $(OBJS) example.o $(LDFLAGS) -o example.elf
        @echo "Creating .hex file"
        @arm-none-eabi-objcopy -O ihex example.elf example.hex
        @echo "Creating .bin file"
        @arm-none-eabi-objcopy -O binary -S example.elf example.bin


afile: libexample.a
        @echo Compiling
        @arm-none-eabi-gcc -c $(CFLAGS) $(INCLUDE) example.c -o example.o
        @echo "Linking (creating .elf)"
        @arm-none-eabi-gcc -L. -lexample example.o $(LDFLAGS) -o example2.elf
        @echo "Creating .hex file"
        @arm-none-eabi-objcopy -O ihex example2.elf example2.hex
        @echo "Creating .bin file"
        @arm-none-eabi-objcopy -O binary -S example2.elf example2.bin

example.bin size is 172K
example2.bin  size is 144K

Parents
  • why are the Int Handlers removed when linked with the archive library and not removed when linked with objects only?

    When the object files are provided to the linker directly on the commandline, it has no choice but to link them fully. But when the object files are provided wrapped within an archive file, the linker does choose which files to link and which file to leave, depending on what symbols it needs to resolve.

    It is a good practice to list the .o files, if any, first on the linker commandline before listing any libraries. There's a proper order, in general, to list the libraries too.

    why are int handlers not removed when linked with "reduced" archive! This is strange ...

    How are the interrupt/exception handler symbols declared? Are they weak symbols, declared as aliases to a dummy/default handler?

    If so, it seems likely that when linking with the full archive file, the linker resolves some handlers, like BusFault_Handler, as the dummy/default handler.


    This could happen if (a) the actual BusFault_Handler is defined in an object file which is later in the order than the object file containing the dummy/default handler, and if (b) the symbols that the linker need to resolve are such that the object file containing the actual BusFault_Handler isn't needed.

    Removing unnecessary object files both change the order of the files in the archive and/or expose other object files which were earlier 'hidden' behind the files just removed. (hidden in the context of resolving a particular symbol).

    When linking with the reduced archive, it is likely that the linker is now forced to include object files containing the actual definitions of those handlers, and therefore, the handlers become available.

    The -Wl,--target-symbol=symbol_name option prints out the references to the given symbol_name and the particular definition the linker found in order to resolve those references. You can check, for e.g., for BusFault_Handler in the two cases - one linking with the full archive and other linking with the reduced archive.

    You may also want to change the order in which you specify the files when creating the full archive. For e.g., provide the object files containing the actual handler functions first, and the rest later.

    Or, in the end, apply --whole-archive to fall back to the ofiles behaviour.

    Edit: Above, replace --target-symbol with --trace-symbol. Apologies. I am not sure what I was thinking at the moment that led me to write --target-symbol instead of --trace-symbol.

Reply
  • why are the Int Handlers removed when linked with the archive library and not removed when linked with objects only?

    When the object files are provided to the linker directly on the commandline, it has no choice but to link them fully. But when the object files are provided wrapped within an archive file, the linker does choose which files to link and which file to leave, depending on what symbols it needs to resolve.

    It is a good practice to list the .o files, if any, first on the linker commandline before listing any libraries. There's a proper order, in general, to list the libraries too.

    why are int handlers not removed when linked with "reduced" archive! This is strange ...

    How are the interrupt/exception handler symbols declared? Are they weak symbols, declared as aliases to a dummy/default handler?

    If so, it seems likely that when linking with the full archive file, the linker resolves some handlers, like BusFault_Handler, as the dummy/default handler.


    This could happen if (a) the actual BusFault_Handler is defined in an object file which is later in the order than the object file containing the dummy/default handler, and if (b) the symbols that the linker need to resolve are such that the object file containing the actual BusFault_Handler isn't needed.

    Removing unnecessary object files both change the order of the files in the archive and/or expose other object files which were earlier 'hidden' behind the files just removed. (hidden in the context of resolving a particular symbol).

    When linking with the reduced archive, it is likely that the linker is now forced to include object files containing the actual definitions of those handlers, and therefore, the handlers become available.

    The -Wl,--target-symbol=symbol_name option prints out the references to the given symbol_name and the particular definition the linker found in order to resolve those references. You can check, for e.g., for BusFault_Handler in the two cases - one linking with the full archive and other linking with the reduced archive.

    You may also want to change the order in which you specify the files when creating the full archive. For e.g., provide the object files containing the actual handler functions first, and the rest later.

    Or, in the end, apply --whole-archive to fall back to the ofiles behaviour.

    Edit: Above, replace --target-symbol with --trace-symbol. Apologies. I am not sure what I was thinking at the moment that led me to write --target-symbol instead of --trace-symbol.

Children