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

arm-none-eabi-ld: Cannot set target architecture

Hi GNU ld experts!

This question is related to a StackOverflow discussion, how GNU ld handles architecture mismatches.

When the ELF objects are compiled in a different architecture than the target architecture from GNU ld.

Without passing GNU ld a target architecture, GNU ld detects the architecture in the ELF objects and

link the objects in a binary. If there are some mismatches with the object files, then GNU ld refuse the linking

with an error.

Issue #1

It isn't possible to pass the architecture to ARM GNU ld when passing the architecture via command line.

The option will not recognized and GNU ld abort with an error.

Issue #2

When trying to use a linker script and set the output architecture here, it leads in many errors

with mismatching EABI version. I have tried to find a option how to set the target EBAI version with

GNU ld, but currently didn't find the correct option, if this is possible.

On none-ARM architectures like AVR from Microchip (formerly Atmel) there are no issues with GNU ld

when setting the target architecture.

  • Check the section 'Secondary compatibility tag' in the ABI errata doc. Check the source code for ld.

    If one tries to link armv4 and armv6-m, that fails. The ld source code for arm does explicitly deal with compatibility of differing arm architectures, perhaps guided by the ABI.

    The author of the stackoverflow article writes:

    Long: I just learned that ld has no issues or concerns about linking an armv4 object into an armv6-m binary despite this beeing very obvious nonsense"

    But in their update, they were actually linking arm4t+armv6-m, and not armv4+armv6-m as they originally described. The test shows that armv4+armv6-m fails. And armv4t+armv6-m is considered compatible, as the ABI errata says:

    At this release of the ABI (2019Q4) there are only two defined uses of Tag_also_compatible_with:

    To express v4T also compatible with v6-M and v6-M also compatible with v4T.

    Thus, it seems that the linker is working as expected, and I fail to see an issue.

    Did they check the behaviour of gold/mold/lld?

    If this compatibility is such an obvious error, they should open a support case with Arm to have the ABI rectified. Once the ABI is corrected, the linkers will be too.

  • Hi!

    Thanks for the quick answer.

    I don't tried the same architectures as the original author on StackOverflow.

    Tried this on my current projects with a Cortex-M7 (Armv7E-M).

    I compiled the source code with the following GCC options:

    CCFLAGS		+= -march=armv7e-m
    CCFLAGS		+= -mcpu=cortex-m7

    Without selecting the target architecture with GNU ld, GNU ld detects the correct architecture.

    But when I use a linker script with selecting the output target architecture...

    OUTPUT_ARCH(armv7e-m)
    OUTPUT_FORMAT(elf32-littlearm)

    ...the linking fails with EABI version mismatches...

    arm-none-eabi-ld: error: source object main.o has EABI version 5, but target main_cm7.elf has EABI version 0
    arm-none-eabi-ld: failed to merge target specific data of file main.o

    I used the following GNU toolchain version binaries from the ARM site:

    $ arm-none-eabi-ld --version
    GNU ld (GNU Arm Embedded Toolchain 10.3-2021.07) 2.36.1.20210621
    Copyright (C) 2021 Free Software Foundation, Inc.
    This program is free software; you may redistribute it under the terms of
    the GNU General Public License version 3 or (at your option) a later version.
    This program has absolutely no warranty.

    Currently don't tried a newer version.

    I will try gold/mold/lld, if there is the same issue and also look into the GNU ld sources.

    Thanks for the links, I will check them too.

    EDIT:

    I invoke GNU ld directly in the Makefile, not via GCC.

    Can also post the full Makefile and the full linker script, which I currently use for my projects.

  • Thank you for the details. I understand the issue now.

    The ld linker does scan for the OUTPUT_ARCH(armv7e-m) in its list of archs/processors and does find a match for armv7e-m. But when the arch is non-default, the linker fails to correctly set the output format. At this line, if a check: if(in_flags == 0) {elf_flags_init (obfd) = false; return true;} is added, the link can be made to succeed.

    For the non-default (i.e. failing) argument, it marks the output flags as initialized even if the input flags are 0 i.e. not initialized. For the default (i.e. success) case, it does not mark the output flag as initialized if the input flags are 0. The above one-liner check resets the output flag marks the output flag as uninitialized if it finds that the input flags are 0. The link succeeds but I do not know enough to say if this is a problem, or not.

    Note that OUTPUT_ARCH(arm) still works - it correctly sets armv7e-m in the final output binary. If other linkers succeed with force-setting a non-default OUTPUT_ARCH, then this could indicate a problem with ld. I haven't checked ld.gold, or mold, or lld yet.

  • Confirmed that ld.gold works with OUTPUT_ARCH(armv7e-m). This indicates a bug with GNU ld.

  • Thank you for the detailed explanation and confirmation!

    Should I report this issue back to ARM or to the GNU bug tracker, if this issue isn't known yet?

  • Done.

    Here is the link to the bug report.