Poohl
Poohl

Reputation: 1924

GNU ld warn about mismatching ARM architecture version?

TLDR: Is there some tool/linker-option to ensure that all object files that will be linked are actually built for the same architecture? Ideally something that can be set as alias for ld.

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. Especially since objdump can figure out what architecture something was built for, this seems worth at least a warning.

I can't find anything in the manpages, the linker doesn't even accept the architecture as argument. The best I could think of is adding something like the follwing to my compilation targets, but that wouldn't protect me from this on the command line where the error is more likely to happen.

[ $(objdump -f $@ | grep -oE 'architecture:\s[^,]+,') == "architecture:${arch}," ]

So is there some way to ensure that any call to ld when given objects for mismatching architectures aborts with error?

Update:

Upvotes: 1

Views: 864

Answers (1)

user10008009
user10008009

Reputation:

To answer you first question, without a given linker option, ld detects the input architecture from the ELF objects and refuse the linking of the objects with an error if there is a mismatch.

The output should be similar to this:

arm-none-eabi-ld: error: main.o: conflicting CPU architectures 13/1
arm-none-eabi-ld: failed to merge target specific data of file main.o

Why ld links an armv4 object into an armv6-m binary without warning/error?

This is just a guess, but it could be possible that the machine code (instructions) from armv4 is compatible with armv6-m. But without my knowledge from the GNU ld code I can't give a clear answer. So I don't know how ld handles this.

Why ld doesn't accept the target architecture from command line?

I have tried this and I can confirm this behaviour. It could be possible, that this is a bug or configuration issue from GNU ld. Will ask this on the official ARM developer community and provide a cross link here. A workaround is to specify the target architecture in a linker script with OUTPUT_ARCH. If the architecture is specified, ld also refuse the linking with an error.

UPDATE:
I have to admit, that I had gone out that this works (setting the output architecture via linker script) also on ARM GNU ld, like on other architectures like AVR from Microchip. But it leads in many EABI version mismatches. I also asked this in the official ARM developer community.

The link to the question on ARM developer community.

UPDATE 1:
The workaround with setting the output architecture (OUTPUT_ARCH) with the linker script, works with the GNU gold linker. Confirmed by a ARM developer community member. You can read this in the above link. The behaviour with the EABI version mismatches indicates a bug in GNU ld.

I have tried this on my current projects with a Cortex-M7 (Armv7E-M).

Compiled the source code with the GCC options:

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

Selected the output target architecture in the linker script:

OUTPUT_ARCH(armv7e-m)

The linking with GNU ld fails here with many of these EABI 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

When using GNU gold instead of GNU ld the linking works, without the EABI mismatches, confirmed by a ARM developer community member.

NOTE
This issue from GNU ld affects at least the official GNU toolchain binaries with the GNU ld version 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 newer or older versions.

UPDATE 2:
I have written an bug report for GNU-ld. Can be found here.

Upvotes: 3

Related Questions