How to convert c to elf using clang and using ld.lld

I am trying to compile the c file to elf format.How can I use the linker and starter files in llvm

clang --target=riscv64 -march=rv64g_zba_zbb_zbc_zbs -mcmodel=medany -static -std=gnu99 -nostartfiles -fno-common -Wall -Werror  -ffunction-sections -fdata-sections  -nostartfiles -lm -lgcc -Wl,--gc-sections -march=rv64i_zba_zbb_zbc_zbs /home/init.s -T/home/link.ld  /home/syscalls.c -o /home/user/Desktop/bare.elf
clang-14: error: argument unused during compilation: '-nostartfiles' [-Werror,-Wunused-command-line-argument]
clang-14: error: argument unused during compilation: '-nostartfiles' [-Werror,-Wunused-command-line-argument]

How can I use linker script support for ELF ld.lld ?

Whether this is correct or not, clang’s bare metal toolchain driver doesn’t check for that option (clang/lib/Driver/ToolChains/BareMetal.cpp).

It does appear to check for nostdlib and nodefaultlibs (more on them here Link Options (Using the GNU Compiler Collection (GCC))).

You’ll probably be fine downgrading that error to a warning, assuming you want to keep -Werror.

$ ./bin/clang --target=riscv64 /tmp/test.c -o /tmp/test.o -nostartfiles -Werror -Wno-error=unused-command-line-argument
clang-16: warning: argument unused during compilation: '-nostartfiles' [-Wunused-command-line-argument]

Or remove nostartfiles and use the other two options.

Then double check the resulting file has what you expect in it. It may be that the driver should in fact be paying attention to nostartfiles, or it could be that the other two in combination produce the same result.

1 Like

I have added the following removing the nostartfiles keeping other two options
clang -v --target=riscv64 -march=rv64g_zba_zbb_zbc_zbs -mcmodel=medany -static -std=gnu99 -fno-common -Wall -Werror -Wno-error=unused-command-line-argument -ffunction-sections -fdata-sections -lm -lgcc -Wl,--gc-sections -march=rv64i_zba_zbb_zbc_zbs /home/cpslab/Downloads/riscv-master/demo/baremetal/init.s -T/home/link.ld /home/syscalls.c -o /home/cpslab/Desktop/bare.elf
I got the following error

clang version 14.0.6 (GitHub - llvm/llvm-project: The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Note: the repository does not accept github pull requests at this moment. Please submit your patches at http://reviews.llvm.org. f28c006a5895fc0e329fe15fead81e37457cb1d1)
Target: riscv64–
Thread model: posix
InstalledDir: /usr/local/bin
“/usr/local/bin/clang-14” -cc1as -triple riscv64-- -filetype obj -main-file-name init.s -target-feature +zba -target-feature +zbb -target-feature +zbc -target-feature +zbs -target-feature +relax -target-feature -save-restore -fdebug-compilation-dir=/ -dwarf-debug-producer “clang version 14.0.6 (GitHub - llvm/llvm-project: The LLVM Project is a collection of modular and reusable compiler and toolchain technologies. Note: the repository does not accept github pull requests at this moment. Please submit your patches at http://reviews.llvm.org. f28c006a5895fc0e329fe15fead81e37457cb1d1)” -dwarf-version=5 -mrelocation-model static -target-abi lp64 -mrelax-all --mrelax-relocations -o /tmp/init-67a8ba.o /home/cpslab/Downloads/riscv-master/demo/baremetal/init.s
“/usr/local/bin/clang-14” -cc1 -triple riscv64-- -emit-obj -mrelax-all --mrelax-relocations -disable-free -clear-ast-before-backend -main-file-name syscalls.c -static-define -mrelocation-model static -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -fno-verbose-asm -mconstructor-aliases -nostdsysteminc -mcmodel=medium -target-feature +zba -target-feature +zbb -target-feature +zbc -target-feature +zbs -target-feature +relax -target-feature -save-restore -target-abi lp64 -msmall-data-limit 8 -mllvm -treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/ -resource-dir /usr/local/lib/clang/14.0.6 -isysroot /riscv64-unknown-elf/ -internal-isystem /usr/local/lib/clang/14.0.6/include -internal-isystem /riscv64-unknown-elf/include -Wall -Werror -Wno-error=unused-command-line-argument -std=gnu99 -fdebug-compilation-dir=/ -ferror-limit 19 -fno-signed-char -fgnuc-version=4.2.1 -fcolor-diagnostics -faddrsig -o /tmp/syscalls-d66328.o -x c /home/cpslab/Downloads/riscv-master/demo/baremetal/syscalls.c
clang -cc1 version 14.0.6 based upon LLVM 14.0.6 default target riscv64-unknown-elf
ignoring nonexistent directory “/riscv64-unknown-elf/include”
ignoring duplicate directory “/usr/local/lib/clang/14.0.6/include”
#include “…” search starts here:
#include <…> search starts here:
/usr/local/lib/clang/14.0.6/include
End of search list.
“ld.lld” -lm -lgcc --gc-sections /tmp/init-67a8ba.o /tmp/syscalls-d66328.o -Bstatic -T /home/cpslab/Downloads/riscv-master/demo/baremetal/link.ld -L/riscv64-unknown-elf/lib -L/usr/local/lib/clang/14.0.6/lib/baremetal -lc -lm -lclang_rt.builtins-riscv64 -o /home/cpslab/Desktop/bare.elf
clang-14: error: unable to execute command: Executable “ld.lld” doesn’t exist!
clang-14: error: ld.lld command failed with exit code 1 (use -v to see invocation)

Is this the correct way to specify init.s and link.ld ?

“ld.lld” -lm -lgcc --gc-sections /tmp/init-67a8ba.o /tmp/syscalls-d66328.o -Bstatic -T /home/cpslab/Downloads/riscv-master/demo/baremetal/link.ld -L/riscv64-unknown-elf/lib -L/usr/local/lib/clang/14.0.6/lib/baremetal -lc -lm -lclang_rt.builtins-riscv64 -o /home/cpslab/Desktop/bare.elf

These linker options look reasonable. The real error is:

clang-14: error: unable to execute command: Executable “ld.lld” doesn’t exist!

Solving this will depend on how you have sourced clang. clang is defaulting to using lld but you do not have ld.lld (which is usually a symlink to the real lld, telling it to act in a certain mode) in the usual search paths.

Those are probably:

If you are able to run simply clang then clang must be on your PATH already so check that you have also installed lld, or that it is included in the release package you downloaded, next to clang.

You’ll know you’ve fixed the issue when you can run ld.lld from the command line.

If for some reason adding to PATH is not possible, you can also add the directory containing ld.lld to clang’s search paths using the -B option (Directory Options (Using the GNU Compiler Collection (GCC)), gcc docs but clang implements it too).

I have succeeded to include lld. But the following error appeared

ld.lld: error: unable to find library -lgcc
ld.lld: error: unable to find library -lclang_rt.builtins-riscv64
clang-14: error: ld.lld command failed with exit code 1 (use -v to see invocation)

The following is the configuration of llvm.

cmake -G Ninja -DLLVM_ENABLE_PROJECTS=“clang;lld”
-DCMAKE_BUILD_TYPE=Debug
-DBUILD_SHARED_LIBS=on
-DLLVM_USE_LINKER=lld
-LLVM_ENABLE_LIBC=on
-LLVM_ENABLE_LLD:on
-DDEFAULT_SYSROOT=$RISCV/riscv64-unknown-elf/
-DGCC_INSTALL_PREFIX=$RISCV/
-DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-elf
…/llvm

Also I have already added the LLVM to PATH.

To minimize the error I tried the following configuration but again landed in build error.

cmake -G Ninja -DLLVM_ENABLE_PROJECTS=“clang;lld;compiler-rt;libc” \

           -DCMAKE_BUILD_TYPE=Debug\
           -DBUILD_SHARED_LIBS=on \
           -DLLVM_USE_LINKER=lld\
           -LLVM_ENABLE_LIBC=on\
           -LLVM_ENABLE_LLD:on\
           -DDEFAULT_SYSROOT=$RISCV/riscv64-unknown-elf/ \
           -DGCC_INSTALL_PREFIX=$RISCV/ \
           -DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-elf \
           ../llvm

Could you suggest the missing flag in this configuration to minimize the error?

We are getting a bit outside my expertise but I can give some pointers at least.

Adding compiler-rt to the build was a good call.

I think you might have to pass --rtlib to clang as described here Assembling a Complete Toolchain — Clang 16.0.0git documentation. That might also fix the -lgcc issue (in essence, by not using libgcc at all).

In general it’s worth reading through Assembling a Complete Toolchain — Clang 16.0.0git documentation if you haven’t already (I wasn’t aware that page existed until just now).

1 Like

I could not run baremetal code .As baremetal does not require library function and linker is looking for -lgcc library we are confused .