ARM baremetal linking

Hello,

I'm trying to build an image using LLVM toolchain and one of the
problems I have is that I don't know how to link. With GCC toolchain
it's this:

arm-none-eabi-ld --entry=__start -T/usr/home/meka/repos/nuttx/nuttx/configs/nucleo-f4x1re/scripts/f401re.ld -L"/usr/home/meka/repos/nuttx/nuttx/staging" -L"/usr/home/meka/repos/nuttx/nuttx/arch/arm/src/board" -o "/usr/home/meka/repos/nuttx/nuttx/nuttx" --start-group -lsched -ldrivers -lconfigs -lc -lmm -larch -lxx -lapps -lfs -lbinfmt -lxx -lboard "/usr/lib/libgcc.a" --end-group

If I substitute arm-none-eabi-ld with ld.lld, I get the following error:

ld.lld: error: target emulation unknown: -m or at least one .o file required

I can't figure out what should I give it as argument to -m. Of course,
giving it at least one .o file works.

Regards,
meka

Hello,

I'm trying to build an image using LLVM toolchain and one of the
problems I have is that I don't know how to link. With GCC toolchain
it's this:

arm-none-eabi-ld --entry=__start -T/usr/home/meka/repos/nuttx/nuttx/configs/nucleo-f4x1re/scripts/f401re.ld -L"/usr/home/meka/repos/nuttx/nuttx/staging" -L"/usr/home/meka/repos/nuttx/nuttx/arch/arm/src/board" -o "/usr/home/meka/repos/nuttx/nuttx/nuttx" --start-group -lsched -ldrivers -lconfigs -lc -lmm -larch -lxx -lapps -lfs -lbinfmt -lxx -lboard "/usr/lib/libgcc.a" --end-group

If I substitute arm-none-eabi-ld with ld.lld, I get the following error:

ld.lld: error: target emulation unknown: -m or at least one .o file required

I can't figure out what should I give it as argument to -m. Of course,
giving it at least one .o file works.

Hello Goran,

At the moment the emulation is just there to tell LLD which target to
use [*]. In your case ARM. At the moment LLD accepts armelf and
armelf-linux-eabi. However given that LLD can pick up the right target
from the object file and you'll need at least one object file to build
an image I'd just rely on that and leave the -m argument out.

Peter

[*] I think the suffix _fbsd on the emulation can be used to set the
OSABI to ELFOSABI_FREEBSD but it doesn't look like that affects you.

As NuttX links only libraries (if I read the ld command properly),
-m armeabi did the trick for me. The image still fails, but it fails in
the exact same way as using GNU linker, so I would say linking works,
and now it's time for some debugging. :o) Thanx for your help!

Regards,
meka

I lost few days staring at the debugger only to realize that
"/usr/lib/libgcc.a" is my system lib. If I'm right, it comes from
compiler-rt, and what I would need is compiler-rt for baremetal ARM. If
I'm right, as CFLAGS for crosscompile are

-target arm-none-eabi -march=armv7-m -mcpu=cortex-m4

that's the exact chip I would need to build compiler-rt for. How could
this be done? Also, if anyone is working on compiling for armv7-m without
using GNU tools, I'm more than interested in joining forces (hopefully
someone has success).

The reason I think this is true are these commands:

clang -print-libgcc-file-name # using the system lib
/usr/lib/libgcc.a

clang -target arm-none-eabi -print-libgcc-file-name # using the baremetal lib
/usr/lib/clang/6.0.1/lib/libclang_rt.builtins-arm.a

As that's where "/usr/lib/libgcc.a" in original command comes from, I
really hope I figured this right, but do correct me if I'm wrong.

Regards,
meka

PS. I tried to do the same last year, but I felt I need to learn a lot
before dealing with LLVM-only baremetal development, and I did. If you
feel I need some more info/literature, please do point it out, I'm more
than willing to learn.

> arm-none-eabi-ld --entry=__start -T/usr/home/meka/repos/nuttx/nuttx/configs/nucleo-f4x1re/scripts/f401re.ld -L"/usr/home/meka/repos/nuttx/nuttx/staging" -L"/usr/home/meka/repos/nuttx/nuttx/arch/arm/src/board" -o "/usr/home/meka/repos/nuttx/nuttx/nuttx" --start-group -lsched -ldrivers -lconfigs -lc -lmm -larch -lxx -lapps -lfs -lbinfmt -lxx -lboard "/usr/lib/libgcc.a" --end-group
I lost few days staring at the debugger only to realize that
"/usr/lib/libgcc.a" is my system lib. If I'm right, it comes from
compiler-rt, and what I would need is compiler-rt for baremetal ARM. If
I'm right, as CFLAGS for crosscompile are

-target arm-none-eabi -march=armv7-m -mcpu=cortex-m4

that's the exact chip I would need to build compiler-rt for. How could
this be done? Also, if anyone is working on compiling for armv7-m without
using GNU tools, I'm more than interested in joining forces (hopefully
someone has success).

The reason I think this is true are these commands:

clang -print-libgcc-file-name # using the system lib
/usr/lib/libgcc.a

clang -target arm-none-eabi -print-libgcc-file-name # using the baremetal lib
/usr/lib/clang/6.0.1/lib/libclang_rt.builtins-arm.a

As that's where "/usr/lib/libgcc.a" in original command comes from, I
really hope I figured this right, but do correct me if I'm wrong.

Regards,
meka

PS. I tried to do the same last year, but I felt I need to learn a lot
before dealing with LLVM-only baremetal development, and I did. If you
feel I need some more info/literature, please do point it out, I'm more
than willing to learn.

Hello again,

I've written

It is possible to build compiler-rt for v6-m and v7-m although it can
be a bit of a struggle to set up. There are a couple of ways that I
know of. The first is to use the BaremetalARM.cmake cache file in
tools/clang/ and the second is to do a standalone build of
compiler-rt.

There isn't a lot of documentation about using the BaremetalARM.cmake
cache file. The best that I know of is the commit message that I've
quoted below:
Don't defer to the GCC driver for linking arm-baremetal

Also comes with a cmake cache for building the runtime bits:

$ cmake <normal cmake flags> \
   -DBAREMETAL_ARMV6M_SYSROOT=/path/to/sysroot \
   -DBAREMETAL_ARMV7M_SYSROOT=/path/to/sysroot \
   -DBAREMETAL_ARMV7EM_SYSROOT=/path/to/sysroot \
   -C /path/to/clang/cmake/caches/BaremetalARM.cmake \
   /path/to/llvm

https://reviews.llvm.org/D33259

I got this to work a year or so ago. The main missing bit of
information was that this required compiler-rt to be in the runtimes
directory and not in the projects directory as suggested by
Getting Started with the LLVM System — LLVM 16.0.0git documentation it also uses hardware
floating point and the hard-floating point float-abi for v7m which may
not be what you want depending on whether your cortex-m4 has floating
point support.

For building compiler-rt standalone for Arm there is the docs page
https://llvm.org/docs/HowToCrossCompileBuiltinsOnArm.html . That will
be a good place to start. The hardest part is usually fighting your
way past the CMAKE try compile step. I strongly recommend using a
version of cmake >= 3.6 so that you can use the
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY .

Hope that this gets you a little bit further.

Peter

I chose to go with this option, and these are the steps

Remove arm_Thumb1_VFPv2_SOURCES from arm_Thumb1_SOURCES because
Cortext-M4 is Armv7E-M according to ARM Cortex-M - Wikipedia

cmake ../compiler-rt \
  -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
  -DCOMPILER_RT_OS_DIR="baremetal" \
  -DCOMPILER_RT_BUILD_BUILTINS=ON \
  -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
  -DCOMPILER_RT_BUILD_XRAY=OFF \
  -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
  -DCOMPILER_RT_BUILD_PROFILE=OFF \
  -DCMAKE_C_COMPILER=/usr/local/libexec/ccache/clang60 \
  -DCMAKE_C_COMPILER_TARGET="arm-none-eabi" \
  -DCMAKE_AR=/usr/local/bin/llvm-ar60 \
  -DCMAKE_NM=/usr/local/bin/llvm-nm60 \
  -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib60 \
  -DCOMPILER_RT_BAREMETAL_BUILD=ON \
  -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
  -DLLVM_CONFIG_PATH=/usr/local/bin/llvm-config60 \
  -DCMAKE_C_FLAGS="-target arm-none-eabi -march=armv7e-m -mcpu=cortex-m4 -isystem /usr/local/include -isystem /usr/include" \
  -DCMAKE_ASM_FLAGS="-target arm-none-eabi -march=armv7e-m -mcpu=cortex-m4" \
  -DCOMPILER_RT_INCLUDE_TESTS=OFF

After "make && sudo make install" I now have
/usr/local/lib/baremetal/libclang_rt.builtins-arm.a. I'm wondering why
that location, and not what clang60 returns for libgcc which is

clang60 -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -print-libgcc-file-name
/usr/local/llvm60/lib/clang/6.0.1/lib/libclang_rt.builtins-arm.a

Anyway, I linked manually using:

ld.lld60 -m armelf --entry=__start -T/usr/home/meka/repos/nuttx/nuttx/configs/nucleo-f4x1re/scripts/f401re.ld -L"/usr/home/meka/repos/nuttx/nuttx/staging" -L"/usr/home/meka/repos/nuttx/nuttx/arch/arm/src/board" -o "/usr/home/meka/repos/nuttx/nuttx/nuttx" --start-group -lsched -ldrivers -lconfigs -lc -lmm -larch -lxx -lapps -lfs -lbinfmt -lxx -lboard /usr/local/lib/baremetal/libclang_rt.builtins-arm.a --end-group

It seams to almost work as I don't get an error imediatly on entrypoint,
which is good (but not much beyond entrypoint either):

lldb nuttx
(lldb) target create "nuttx"
Current executable set to 'nuttx' (arm).
(lldb) gdb-remote 3333
Process 1 stopped
* thread #1, stop reason = signal SIGINT
    frame #0: 0x08000188 nuttx`__start
nuttx`__start:
-> 0x8000188 <+0>: push {r7, lr}
    0x800018a <+2>: bl 0x800bb30 ; stm32_clockconfig
    0x800018e <+6>: bl 0x8003bd0 ; stm32_lowsetup
    0x8000192 <+10>: bl 0x80009f8 ; stm32_gpioinit
(lldb)

On the WikiPedia link I read that M4 doesn't have FPU, only M4F has it,
so I was wondering if that's the cause of this error. Even if it isn't
the cause of error, how would I build compiler-rt for this chip and
explicitely state that it doesn't have FPU? Also, I obviously need to
build with debug symbols (which I forgot this time), but that should
be easy. Any other tip on how to make more progress is welcome!

Regards,
meka

> For building compiler-rt standalone for Arm there is the docs page
> https://llvm.org/docs/HowToCrossCompileBuiltinsOnArm.html . That will
> be a good place to start. The hardest part is usually fighting your
> way past the CMAKE try compile step. I strongly recommend using a
> version of cmake >= 3.6 so that you can use the
> -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY .
>
> Hope that this gets you a little bit further.
>
> Peter

I chose to go with this option, and these are the steps

Remove arm_Thumb1_VFPv2_SOURCES from arm_Thumb1_SOURCES because
Cortext-M4 is Armv7E-M according to ARM Cortex-M - Wikipedia

cmake ../compiler-rt \
  -DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
  -DCOMPILER_RT_OS_DIR="baremetal" \
  -DCOMPILER_RT_BUILD_BUILTINS=ON \
  -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
  -DCOMPILER_RT_BUILD_XRAY=OFF \
  -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
  -DCOMPILER_RT_BUILD_PROFILE=OFF \
  -DCMAKE_C_COMPILER=/usr/local/libexec/ccache/clang60 \
  -DCMAKE_C_COMPILER_TARGET="arm-none-eabi" \
  -DCMAKE_AR=/usr/local/bin/llvm-ar60 \
  -DCMAKE_NM=/usr/local/bin/llvm-nm60 \
  -DCMAKE_RANLIB=/usr/local/bin/llvm-ranlib60 \
  -DCOMPILER_RT_BAREMETAL_BUILD=ON \
  -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
  -DLLVM_CONFIG_PATH=/usr/local/bin/llvm-config60 \
  -DCMAKE_C_FLAGS="-target arm-none-eabi -march=armv7e-m -mcpu=cortex-m4 -isystem /usr/local/include -isystem /usr/include" \
  -DCMAKE_ASM_FLAGS="-target arm-none-eabi -march=armv7e-m -mcpu=cortex-m4" \
  -DCOMPILER_RT_INCLUDE_TESTS=OFF

After "make && sudo make install" I now have
/usr/local/lib/baremetal/libclang_rt.builtins-arm.a. I'm wondering why
that location, and not what clang60 returns for libgcc which is

clang60 -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -print-libgcc-file-name
/usr/local/llvm60/lib/clang/6.0.1/lib/libclang_rt.builtins-arm.a

By default I think that Clang looks for compiler-rt in the resource
directory, this is usually relative to the clang executable, something
like ../lib/clang/6.0.0/lib/baremetal/libclang_rt.builtins-armv7m.a
for a --target=armv7-m-none-eabi. You can find out where this is with
--print-resource-dir

Anyway, I linked manually using:

ld.lld60 -m armelf --entry=__start -T/usr/home/meka/repos/nuttx/nuttx/configs/nucleo-f4x1re/scripts/f401re.ld -L"/usr/home/meka/repos/nuttx/nuttx/staging" -L"/usr/home/meka/repos/nuttx/nuttx/arch/arm/src/board" -o "/usr/home/meka/repos/nuttx/nuttx/nuttx" --start-group -lsched -ldrivers -lconfigs -lc -lmm -larch -lxx -lapps -lfs -lbinfmt -lxx -lboard /usr/local/lib/baremetal/libclang_rt.builtins-arm.a --end-group

It seams to almost work as I don't get an error imediatly on entrypoint,
which is good (but not much beyond entrypoint either):

lldb nuttx
(lldb) target create "nuttx"
Current executable set to 'nuttx' (arm).
(lldb) gdb-remote 3333
Process 1 stopped
* thread #1, stop reason = signal SIGINT
    frame #0: 0x08000188 nuttx`__start
nuttx`__start:
-> 0x8000188 <+0>: push {r7, lr}
    0x800018a <+2>: bl 0x800bb30 ; stm32_clockconfig
    0x800018e <+6>: bl 0x8003bd0 ; stm32_lowsetup
    0x8000192 <+10>: bl 0x80009f8 ; stm32_gpioinit
(lldb)

If there is a SIGINT on push {r7, lr} that might indicate that the
stack pointer register isn't set correctly. Depending on how your
libraries work you may have to do this yourself prior to entering
__start. Will be worth seeing what SP (R13) is in your debugger at
that point.

On the WikiPedia link I read that M4 doesn't have FPU, only M4F has it,
so I was wondering if that's the cause of this error. Even if it isn't
the cause of error, how would I build compiler-rt for this chip and
explicitely state that it doesn't have FPU? Also, I obviously need to
build with debug symbols (which I forgot this time), but that should
be easy. Any other tip on how to make more progress is welcome!

Adding -mfpu=none -mfloat-abi=soft to the CMAKE_C_FLAGS and
CMAKE_ASM_FLAGS should prevent any use of floating point. There is a
check in the CMake files to remove the VFP sources if a particular
macro isn't defined with the compilation flags so this should make it
unnecessary to manual edit the CMakeLists.txt file.

Peter

By default I think that Clang looks for compiler-rt in the resource
directory, this is usually relative to the clang executable, something
like ../lib/clang/6.0.0/lib/baremetal/libclang_rt.builtins-armv7m.a
for a --target=armv7-m-none-eabi. You can find out where this is with
--print-resource-dir

Strange:

clang60 -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -print-resource-dir
/usr/local/llvm60/lib/clang/6.0.1

clang60 -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -print-libgcc-file-name
/usr/local/llvm60/lib/clang/6.0.1/lib/libclang_rt.builtins-arm.a

If there is a SIGINT on push {r7, lr} that might indicate that the
stack pointer register isn't set correctly. Depending on how your
libraries work you may have to do this yourself prior to entering
__start. Will be worth seeing what SP (R13) is in your debugger at
that point.

I made a mistake when I said it's not breaking on entrypoint. I just
didn't enable debug build, so the lldb output was different. For
completenes, this is the linker command now:

ld.lld60 -m armelf --entry=__start -T/usr/home/meka/repos/nuttx/nuttx/configs/nucleo-f4x1re/scripts/f401re.ld -L"/usr/home/meka/repos/nuttx/nuttx/staging" -L"/usr/home/meka/repos/nuttx/nuttx/arch/arm/src/board" -o "/usr/home/meka/repos/nuttx/nuttx/nuttx" --start-group -lsched -ldrivers -lconfigs -lc -lmm -larch -lxx -lapps -lfs -lbinfmt -lxx -lboard /usr/local/lib/baremetal/libclang_rt.builtins-arm.a --end-group

This is what debugger says when -g is added to CFLAGS:

lldb nuttx
(lldb) target create "nuttx"
Current executable set to 'nuttx' (arm).
(lldb) gdb-remote 3333 Process 1 stopped
* thread #1, stop reason = signal SIGTRAP
    frame #0: 0x08000188 nuttx`__start at stm32_start.c:274
   271 ****************************************************************************/
   272
   273 void __start(void)
-> 274 {
   275 const uint32_t *src;
   276 uint32_t *dest;
   277
(lldb) register read
General Purpose Registers:
        r0 = 0x00000000
        r1 = 0x00000000
        r2 = 0x00000000
        r3 = 0x00000000
        r4 = 0x00000000
        r5 = 0x00000000
        r6 = 0x00000000
        r7 = 0x00000000
        r8 = 0x00000000
        r9 = 0x00000000
       r10 = 0x00000000
       r11 = 0x00000000
       r12 = 0x00000000
        sp = 0x200016c8
        lr = 0xffffffff
        pc = 0x08000188 nuttx`__start at stm32_start.c:274
      cpsr = 0x00000000

(lldb)

In other words, it does break on entrypoint.

Adding -mfpu=none -mfloat-abi=soft to the CMAKE_C_FLAGS and
CMAKE_ASM_FLAGS should prevent any use of floating point. There is a
check in the CMake files to remove the VFP sources if a particular
macro isn't defined with the compilation flags so this should make it
unnecessary to manual edit the CMakeLists.txt file.

I compiled without hardware FPU now. I also added
-DCMAKE_BUILD_TYPE=Debug

GCC build readelf (without debug): ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Clas - Pastebin.com
Clang build readelf (with debug): ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Clas - Pastebin.com

When I diff'ed those two, what I noticed is this:

- Tag_ARM_ISA_use: Yes
+ Tag_ARM_ISA_use: No

Of course, there's tons of differences there, but this one is a bit funky.

Regards,
meka

> By default I think that Clang looks for compiler-rt in the resource
> directory, this is usually relative to the clang executable, something
> like ../lib/clang/6.0.0/lib/baremetal/libclang_rt.builtins-armv7m.a
> for a --target=armv7-m-none-eabi. You can find out where this is with
> --print-resource-dir

Strange:

clang60 -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -print-resource-dir
/usr/local/llvm60/lib/clang/6.0.1

clang60 -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -print-libgcc-file-name
/usr/local/llvm60/lib/clang/6.0.1/lib/libclang_rt.builtins-arm.a

> If there is a SIGINT on push {r7, lr} that might indicate that the
> stack pointer register isn't set correctly. Depending on how your
> libraries work you may have to do this yourself prior to entering
> __start. Will be worth seeing what SP (R13) is in your debugger at
> that point.

I made a mistake when I said it's not breaking on entrypoint. I just
didn't enable debug build, so the lldb output was different. For
completenes, this is the linker command now:

ld.lld60 -m armelf --entry=__start -T/usr/home/meka/repos/nuttx/nuttx/configs/nucleo-f4x1re/scripts/f401re.ld -L"/usr/home/meka/repos/nuttx/nuttx/staging" -L"/usr/home/meka/repos/nuttx/nuttx/arch/arm/src/board" -o "/usr/home/meka/repos/nuttx/nuttx/nuttx" --start-group -lsched -ldrivers -lconfigs -lc -lmm -larch -lxx -lapps -lfs -lbinfmt -lxx -lboard /usr/local/lib/baremetal/libclang_rt.builtins-arm.a --end-group

This is what debugger says when -g is added to CFLAGS:

lldb nuttx
(lldb) target create "nuttx"
Current executable set to 'nuttx' (arm).
(lldb) gdb-remote 3333 Process 1 stopped
* thread #1, stop reason = signal SIGTRAP
    frame #0: 0x08000188 nuttx`__start at stm32_start.c:274
   271 ****************************************************************************/
   272
   273 void __start(void)
-> 274 {
   275 const uint32_t *src;
   276 uint32_t *dest;
   277
(lldb) register read
General Purpose Registers:
        r0 = 0x00000000
        r1 = 0x00000000
        r2 = 0x00000000
        r3 = 0x00000000
        r4 = 0x00000000
        r5 = 0x00000000
        r6 = 0x00000000
        r7 = 0x00000000
        r8 = 0x00000000
        r9 = 0x00000000
       r10 = 0x00000000
       r11 = 0x00000000
       r12 = 0x00000000
        sp = 0x200016c8
        lr = 0xffffffff
        pc = 0x08000188 nuttx`__start at stm32_start.c:274
      cpsr = 0x00000000

(lldb)

In other words, it does break on entrypoint.

Ok. Good luck tracking down where the problem is.

> Adding -mfpu=none -mfloat-abi=soft to the CMAKE_C_FLAGS and
> CMAKE_ASM_FLAGS should prevent any use of floating point. There is a
> check in the CMake files to remove the VFP sources if a particular
> macro isn't defined with the compilation flags so this should make it
> unnecessary to manual edit the CMakeLists.txt file.
I compiled without hardware FPU now. I also added
-DCMAKE_BUILD_TYPE=Debug

GCC build readelf (without debug): ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Clas - Pastebin.com
Clang build readelf (with debug): ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Clas - Pastebin.com

When I diff'ed those two, what I noticed is this:

- Tag_ARM_ISA_use: Yes
+ Tag_ARM_ISA_use: No

Of course, there's tons of differences there, but this one is a bit funky.

Regards,
meka

It looks like the Tag_ARM_ISA_use is from the GCC build (from the
first pastebin link). From the symbol table it looks like there is
some ARM code in there ($a symbols) and from the file symbols most
likely from files _lshrdi3.o, _aeabi_ldivmod.o, _aeabi_uldivmod.o,
libgcc2.c, _dvmd_tls.o, _clzdi2.o and _clzsi2.o . It looks like the
GCC build may be picking up the wrong version of libgcc as I would
expect problems if this ARM code was ever run. Just as an aside are
you using LLD to link the GCC objects? I'd half expect GNU LD to give
you an error message for the presence of ARM code in M-profile.

Peter

Ok. Good luck tracking down where the problem is.

Thanx! Unfortunately, I'll need it. :o(

It looks like the Tag_ARM_ISA_use is from the GCC build (from the
first pastebin link). From the symbol table it looks like there is
some ARM code in there ($a symbols) and from the file symbols most
likely from files _lshrdi3.o, _aeabi_ldivmod.o, _aeabi_uldivmod.o,
libgcc2.c, _dvmd_tls.o, _clzdi2.o and _clzsi2.o . It looks like the
GCC build may be picking up the wrong version of libgcc as I would
expect problems if this ARM code was ever run. Just as an aside are
you using LLD to link the GCC objects? I'd half expect GNU LD to give
you an error message for the presence of ARM code in M-profile.

Peter

GCC is linked with arm-none-eabi-ld and Clang with ld.lld60 (as it's
FreeBSD and it has multiple LLVM packages, binaries are appended with
the version number).