[Driver] Pass --target2= to linker from baremetal toolchain
authorMikhail Maltsev <mikhail.maltsev@arm.com>
Fri, 28 Apr 2023 17:30:49 +0000 (18:30 +0100)
committerMikhail Maltsev <mikhail.maltsev@arm.com>
Fri, 28 Apr 2023 17:30:49 +0000 (18:30 +0100)
According to the GNU ld manual
https://sourceware.org/binutils/docs/ld/ARM.html#ARM the R_ARM_TARGET2
relocation (used in exception handling tables) is treated differently
depending on the target. By default, LLD treats R_ARM_TARGET2 as
R_ARM_GOT_PREL (--target2=got-rel), which is correct for Linux but not
for embedded targets.

This patch adds --target2=rel to linker options in the baremetal
toolchain driver so that on baremetal targets, R_ARM_TARGET2 is
treated as R_ARM_REL32. Such behavior is compatible with GNU ld and
unwinding libraries (e.g., libuwind).

Reviewed By: peter.smith, phosek

Differential Revision: https://reviews.llvm.org/D149458

clang/lib/Driver/ToolChains/BareMetal.cpp
clang/test/Driver/baremetal.cpp

index 38f26d0..3232394 100644 (file)
@@ -342,6 +342,12 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   if (TC.getTriple().isRISCV())
     CmdArgs.push_back("-X");
 
+  // The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
+  // and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
+  // arm*-*-*bsd).
+  if (isARMBareMetal(TC.getTriple()))
+    CmdArgs.push_back("--target2=rel");
+
   CmdArgs.push_back("-o");
   CmdArgs.push_back(Output.getFilename());
 
index 7f23344..c00713a 100644 (file)
@@ -15,7 +15,7 @@
 // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for"
 // CHECK-V6M-C-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib"
 // CHECK-V6M-C-SAME: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}baremetal"
-// CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "-o" "{{.*}}.tmp.out"
+// CHECK-V6M-C-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "--target2=rel" "-o" "{{.*}}.tmp.out"
 
 // RUN: %clang %s -### --target=armv6m-none-eabi -nostdlibinc -nobuiltininc 2>&1 \
 // RUN:     --sysroot=%S/Inputs/baremetal_arm | FileCheck --check-prefix=CHECK-V6M-LIBINC %s
@@ -42,7 +42,7 @@
 // CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib"
 // CHECK-V6M-DEFAULTCXX-SAME: "-L[[RESOURCE_DIR]]{{[/\\]+}}lib{{[/\\]+}}baremetal"
 // CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
-// CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "-o" "a.out"
+// CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "--target2=rel" "-o" "a.out"
 
 // RUN: %clangxx %s -### --target=armv6m-none-eabi -stdlib=libc++ 2>&1 \
 // RUN:     --sysroot=%S/Inputs/baremetal_arm | FileCheck --check-prefix=CHECK-V6M-LIBCXX %s
@@ -53,7 +53,7 @@
 // CHECK-V6M-LIBCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib"
 // CHECK-V6M-LIBCXX-SAME: "-L[[RESOURCE_DIR]]{{[/\\]+}}lib{{[/\\]+}}baremetal"
 // CHECK-V6M-LIBCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
-// CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "-o" "a.out"
+// CHECK-V6M-LIBCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "--target2=rel" "-o" "a.out"
 
 // RUN: %clangxx %s -### --target=armv6m-none-eabi 2>&1 \
 // RUN:     --sysroot=%S/Inputs/baremetal_arm \
@@ -66,7 +66,7 @@
 // CHECK-V6M-LIBSTDCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib"
 // CHECK-V6M-LIBSTDCXX-SAME: "-L[[RESOURCE_DIR]]{{[/\\]+}}lib{{[/\\]+}}baremetal"
 // CHECK-V6M-LIBSTDCXX-SAME: "-lstdc++" "-lsupc++" "-lunwind"
-// CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "-o" "a.out"
+// CHECK-V6M-LIBSTDCXX-SAME: "-lc" "-lm" "-lclang_rt.builtins-armv6m" "--target2=rel" "-o" "a.out"
 
 // RUN: %clangxx %s -### --target=armv6m-none-eabi 2>&1 \
 // RUN:     --sysroot=%S/Inputs/baremetal_arm \