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
  • example.bin size is 172K
    example2.bin  size is 144K

    The size difference is likely due to the fact that the linker can choose the object files to link from an archive, depending on the symbols it needs to resolve. As a result, the size of the output binary may be less than that of a binary built by linking all the object files. (See also the linker option --whole-archive.)

    the resulting elf/bin is malfunction

    What exactly does a malfunction mean? How do the two elf binaries differ, besides in their sizes - any differences in symbols linked, or in the disassemblies of a function?

    These options, if provided to gcc's LDFLAGS, output details about the objects being linked, and about the symbols, their references and definitions:

    • -Wl,--trace,--trace (that's --trace, twice)
    • -Wl,--trace-symbol,symbol_name
    • -Wl,--cref

    With these, you should be able to see how the linker resolves the symbols in the two cases, and detect any differences if there are.

    Does switching from (a) to (b), or from (a) to (c), or from (a) to (d), (see below) make any difference?

    (a)@arm-none-eabi-gcc -L. -lexample example.o $(LDFLAGS) -o example2.elf

    (b)@arm-none-eabi-gcc example.o -L. -lexample $(LDFLAGS) -o example2.elf

    (c)@arm-none-eabi-gcc -Wl,--whole-archive -L. -lexample example.o $(LDFLAGS) -o example2.elf

    (d)@arm-none-eabi-gcc -Wl,--whole-archive example.o -L. -lexample $(LDFLAGS) -o example2.elf

    Note also that the search for objects inside an archive is dependent on the ordering of the objects stored. See here.

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

    The size difference is likely due to the fact that the linker can choose the object files to link from an archive, depending on the symbols it needs to resolve. As a result, the size of the output binary may be less than that of a binary built by linking all the object files. (See also the linker option --whole-archive.)

    the resulting elf/bin is malfunction

    What exactly does a malfunction mean? How do the two elf binaries differ, besides in their sizes - any differences in symbols linked, or in the disassemblies of a function?

    These options, if provided to gcc's LDFLAGS, output details about the objects being linked, and about the symbols, their references and definitions:

    • -Wl,--trace,--trace (that's --trace, twice)
    • -Wl,--trace-symbol,symbol_name
    • -Wl,--cref

    With these, you should be able to see how the linker resolves the symbols in the two cases, and detect any differences if there are.

    Does switching from (a) to (b), or from (a) to (c), or from (a) to (d), (see below) make any difference?

    (a)@arm-none-eabi-gcc -L. -lexample example.o $(LDFLAGS) -o example2.elf

    (b)@arm-none-eabi-gcc example.o -L. -lexample $(LDFLAGS) -o example2.elf

    (c)@arm-none-eabi-gcc -Wl,--whole-archive -L. -lexample example.o $(LDFLAGS) -o example2.elf

    (d)@arm-none-eabi-gcc -Wl,--whole-archive example.o -L. -lexample $(LDFLAGS) -o example2.elf

    Note also that the search for objects inside an archive is dependent on the ordering of the objects stored. See here.

Children
More questions in this forum