Skip to content

[Driver] Include crt0.o in the baremetal link #101258

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 2, 2024

Conversation

petrhosek
Copy link
Member

The common baremetal libc implementations already provide crt0.o and GCC automatically links it so this improves parity.

The common baremetal libc implementations already provide crt0.o and
GCC automatically links it so this improves parity.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' labels Jul 30, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 30, 2024

@llvm/pr-subscribers-clang-driver

@llvm/pr-subscribers-clang

Author: Petr Hosek (petrhosek)

Changes

The common baremetal libc implementations already provide crt0.o and GCC automatically links it so this improves parity.


Full diff: https://github.com/llvm/llvm-project/pull/101258.diff

4 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/BareMetal.cpp (+5)
  • (added) clang/test/Driver/Inputs/baremetal_arm/lib/crt0.o ()
  • (added) clang/test/Driver/Inputs/basic_baremetal_tree/lib/armv6m-unknown-none-eabi/crt0.o ()
  • (modified) clang/test/Driver/baremetal.cpp (+8)
diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp
index 852e0442f50a2..102d12700229e 100644
--- a/clang/lib/Driver/ToolChains/BareMetal.cpp
+++ b/clang/lib/Driver/ToolChains/BareMetal.cpp
@@ -487,6 +487,11 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
   }
 
+  if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
+                   options::OPT_r)) {
+    CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o")));
+  }
+
   Args.addAllArgs(CmdArgs, {options::OPT_L, options::OPT_T_Group,
                             options::OPT_s, options::OPT_t, options::OPT_r});
 
diff --git a/clang/test/Driver/Inputs/baremetal_arm/lib/crt0.o b/clang/test/Driver/Inputs/baremetal_arm/lib/crt0.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/basic_baremetal_tree/lib/armv6m-unknown-none-eabi/crt0.o b/clang/test/Driver/Inputs/basic_baremetal_tree/lib/armv6m-unknown-none-eabi/crt0.o
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/baremetal.cpp b/clang/test/Driver/baremetal.cpp
index de4e93434e203..9814bf7b0a395 100644
--- a/clang/test/Driver/baremetal.cpp
+++ b/clang/test/Driver/baremetal.cpp
@@ -16,6 +16,7 @@
 // CHECK-V6M-C-SAME: "-internal-isystem" "[[SYSROOT]]{{[/\\]+}}include"
 // CHECK-V6M-C-SAME: "-x" "c++" "{{.*}}baremetal.cpp"
 // CHECK-V6M-C-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL"
+// CHECK-V6M-C-SAME: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o"
 // CHECK-V6M-C-SAME: "-T" "semihosted.lds" "-Lsome{{[/\\]+}}directory{{[/\\]+}}user{{[/\\]+}}asked{{[/\\]+}}for"
 // CHECK-V6M-C-SAME: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib"
 // CHECK-V6M-C-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "{{.*}}.tmp.out"
@@ -37,6 +38,7 @@
 // CHECK-V6M-TREE-SAME: "-internal-isystem" "[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}include{{[/\\]+}}armv6m-unknown-none-eabi"
 // CHECK-V6M-TREE-SAME: "-x" "c++" "{{.*}}baremetal.cpp"
 // CHECK-V6M-TREE-NEXT: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL"
+// CHECK-V6M-TREE-SAME: "[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}armv6m-unknown-none-eabi{{[/\\]+}}crt0.o"
 // CHECK-V6M-TREE-SAME: "-L[[INSTALLED_DIR]]{{[/\\]+}}..{{[/\\]+}}lib{{[/\\]+}}armv6m-unknown-none-eabi"
 // CHECK-V6M-TREE-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "{{.*}}.tmp.out"
 
@@ -48,6 +50,7 @@
 // CHECK-ARMV7M-PER-TARGET: "-isysroot" "[[SYSROOT:[^"]*]]"
 // CHECK-ARMV7M-PER-TARGET: "-x" "c++" "{{.*}}baremetal.cpp"
 // CHECK-ARMV7M-PER-TARGET: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL"
+// CHECK-ARMV7M-PER_TARGET: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o"
 // CHECK-ARMV7M-PER-TARGET: "-L[[SYSROOT:[^"]+]]{{[/\\]+}}lib"
 // CHECK-ARMV7M-PER-TARGET: "-L[[RESOURCE_DIR:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}armv7m-vendor-none-eabi
 // CHECK-ARMV7M-PER-TARGET: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a"
@@ -56,6 +59,7 @@
 // RUN:     --sysroot=%S/Inputs/baremetal_arm | FileCheck --check-prefix=CHECK-V6M-DEFAULTCXX %s
 // CHECK-V6M-DEFAULTCXX: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]"
 // CHECK-V6M-DEFAULTCXX: ld{{(.exe)?}}" "{{.*}}.o" "-Bstatic" "-EL"
+// CHECK-V6M-DEFAULTCXX-SAME: "[[SYSROOT:[^"]+]]{{[/\\]+}}lib{{[/\\]+}}crt0.o"
 // CHECK-V6M-DEFAULTCXX-SAME: "-L{{[^"]*}}{{[/\\]+}}Inputs{{[/\\]+}}baremetal_arm{{[/\\]+}}lib"
 // CHECK-V6M-DEFAULTCXX-SAME: "-lc++" "-lc++abi" "-lunwind"
 // CHECK-V6M-DEFAULTCXX-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a" "--target2=rel" "-o" "a.out"
@@ -105,6 +109,10 @@
 // CHECK-V6M-LIBCXX-USR-SAME: "-lc++" "-lc++abi" "-lunwind"
 // CHECK-V6M-LIBCXX-USR-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a"
 
+// RUN: %clangxx --target=arm-none-eabi -nostartfiles -v 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-NOSTARTFILES
+// CHECK-NOSTARTFILES-NOT: "crt0.o"
+
 // RUN: %clangxx --target=arm-none-eabi -v 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=CHECK-THREAD-MODEL
 // CHECK-THREAD-MODEL: Thread model: posix

@@ -105,6 +109,10 @@
// CHECK-V6M-LIBCXX-USR-SAME: "-lc++" "-lc++abi" "-lunwind"
// CHECK-V6M-LIBCXX-USR-SAME: "-lc" "-lm" "{{[^"]*}}libclang_rt.builtins.a"

// RUN: %clangxx --target=arm-none-eabi -nostartfiles -v 2>&1 \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-v without an input file doesn't print commands. -### ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@smithp35
Copy link
Collaborator

One thing the GNU toolchain does with specs files is to rename the crt0.o when semihosting, or other variants are used, for example the --specs=rdimon.specs will add rdimon-crt0.o rather than crt0.o
The part in the specs file is:

*startfile:
crti%O%s crtbegin%O%s %{!pg:rdimon-crt0%O%s} %{pg:rdimon-crt0%O%s}

In picolibc we've kind of worked around this by using a crt library rather than an object file for example libcrt0.a libcrt0-semihosting.a that way we've been able to mimic the specs file by adding -lcrt0-semihosting this uses the library path added by multilib to find the libcrt0.a library without the user having to know the path to the crt0-semihosting.o object file.

I don't think this is fundamentally incompatible with unconditionally adding crt0.o as -nostartfiles can be used to suppress it. I'm wondering if in the future we might be able to offer an option to add a prefix to the crt0.o.

Picolibc reference:
https://github.com/picolibc/picolibc/blob/61560a1a4bfd78d0be3a36d0507cbeb795eebddb/picocrt/meson.build#L72

@petrhosek petrhosek merged commit 983869a into llvm:main Aug 2, 2024
7 checks passed
dcandler added a commit to dcandler/LLVM-embedded-toolchain-for-Arm that referenced this pull request Aug 5, 2024
This commit adds the -nostartfiles option to tests using semihosting.
This is in response to a recent change in clang which modified the
driver to include crt0.o in the link:
llvm/llvm-project#101258

While the change to clang removes the need to include the crt0
library directly, the tests using semihosting need to link against a
different crt0 library. Therefore the new default behavior needs to
be suppressed in these cases, which can be done by adding
the -nostartfiles option.
dcandler added a commit to ARM-software/LLVM-embedded-toolchain-for-Arm that referenced this pull request Aug 5, 2024
* Do not default to linking crt0 when using crt0-semihosting

This commit adds the -nostartfiles option to tests using semihosting.
This is in response to a recent change in clang which modified the
driver to include crt0.o in the link:
llvm/llvm-project#101258

While the change to clang removes the need to include the crt0
library directly, the tests using semihosting need to link against a
different crt0 library. Therefore the new default behavior needs to
be suppressed in these cases, which can be done by adding
the -nostartfiles option.

* Also remove -lcrt0 from make.bat
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants