ld.lld: error: undefined symbol: __divdi3 - clang

I'm trying to link two risc-v elf files together with ld.lld, but ld.lld is giving me the following error:
ld.lld: error: undefined symbol: __divdi3
I suppose that I need to link my files with some helper functions, but after looking for it in my clang lib folder (/usr/local/Cellar/llvm/15.0.6/lib/clang/15.0.6/lib), but in the directory, there is only a folder for darwin, as you can see here:
.
└── darwin
├── libclang_rt.asan_osx_dynamic.dylib
├── libclang_rt.cc_kext.a
├── libclang_rt.fuzzer_interceptors_osx.a
[more]
├── libclang_rt.xray-profiling_osx.a
└── libclang_rt.xray_osx.a
So does anyone know how should I fix this link error/get the rv64i helper functions?
Thanks!
Edit: Here are the commands that I used:
/usr/local/Cellar/llvm/15.0.6/bin/clang --target=riscv64 -march=rv64i -fno-builtin -nostdlib -ffreestanding -Wall -Wextra -Wwrite-strings -Wstrict-prototypes -pedantic -c -o build/main.o bios/main.c
riscv64-unknown-elf-as -march=rv64i -o build/start.o src/start.S
/usr/local/Cellar/llvm/15.0.6/bin/ld.lld -T link.ld -O2 -nostdlib --oformat=binary -o output.bin build/main.o build/start.o

You can get a copy of the source of the functions in libgcc here: https://github.com/gcc-mirror/gcc/tree/releases/gcc-12/libgcc/config/riscv Just copy them and place them in your source and they will compile for whatever arch your compiling for
The function __divdi3 is in the div.c file

__divdi3 is as a routine from the compiler supporting library. In case of gcc it is called libgcc, in case of clang it's compiler-rt. You need to have compiler-rt built from the architecture in question (RISC-V) and make it available to compiler via e.g. sysroot or something similar (or link explicitly).
Alternatively, just do not use 64-bit division in your program, so the call will not be generated :)

Related

ClangCodeModel in QtCreator says "module not found" on imported C++20 modules

I use QtCreator 4.15.2, clang 12.0.1.
I have "generic project" with makefile. File src/test/main.cpp contains import test.StringUtil;. QtCreator complains that module is not found. (Project builds ok, but makefile uses gcc; I'm not familiar with clang.) I tried this:
Generated .pcm file in separate directory:
clang++ -std=c++20 -fmodules --precompile -x c++-module src/test/StringUtil.cpp -o target/clang/test.StringUtil.pcm
Edited myproject.cxxflags in project root so it contains:
-std=c++20 -fmodules -fprebuilt-module-path=/home/me/myproject/target/clang -Wall -Wextra -Wpedantic -fno-rtti
If I specify relative path -fprebuilt-module-path=target/clang then nothing changes; QtCreator still says that module not found. But with absolute path looks like ClangCodeModel gets disabled (crashes?): <No Symbols> in QtCreator's symbols combobox, no syntax errors reporting.
I also tried to compile in additiion to generating .pcm file, with no difference:
clang++ -std=c++20 -fmodules -c -x c++-module src/test/StringUtil.cpp -o target/build/clang/test.StringUtil.o
So: how do I make it work?
When I added support for modules in my own build system I found it easiest to specify each imported module with the flag -fmodule-file="path/to/other.pcm".
In the future I guess that the big build systems will do this aswell. since you need to preprocess the files anyway there is no extra cost. (It could be some extra work if you write your makefiles by hand though)
I don't think that qtcreators code model supports modules as of yet. I have tried but it does not work for me.

what are the rules zig build-lib uses for shared objects filenames?

I have a sqlite extension file. The source is sqliteext/csv.c. When I build the lib with clang the output file is created at lib/csv.so.
cc -g -fPIC -I /usr/local/include -shared sqliteext/csv.c -o lib/csv.so
When I compile the lib using zig...
zig build-lib -I /usr/local/include -I /usr/include -I /usr/include/x86_64-linux-gnu --c-source sqliteext/csv.c -dynamic --output-dir lib
There are two problems.
zig prefixes the filename with a lib
zig add a version number thing in the suffix
so the output file is lib/libcsv.so.0.0.0
And what's interesting about this is that I need to change the filename in my extension loader (that's ok) but that I also need a symlink to handle the 0.0.0.
I'm still looking at the CLI help but I'm still not seeing the thing I need.
See https://github.com/ziglang/zig/issues/2230 and https://github.com/ziglang/zig/issues/2231
The former was fixed the same day as your post via https://github.com/ziglang/zig/pull/6315

How to update shared library file

I'm trying to add a .lo object file compiled through libtool with clang into a shared library file.
$ libtool --tag=CC --mode=compile clang -c newobject.c -shared
Is there an equivalent command to
$ ar r libmylib.a newobject.o
for shared libraries?
Alternatively, is there a way to dump all the .lo files that are already contained in a .so file so I can re-create tne shared library, say, using this command?
$ libtool --mode=link ld -soname libmylib.so -o libmylib.so.1 libmylib.so.0 newobject.o
There is no way to incrementally alter a shared library. You need all the component object files and rebuild the shared library from those each time.
I don't know of a way to extract object files from a shared library.

How can I insert tcov to Make File

How can i use tcov on Solaris in make file? My make file makes .o files and then the .so files which is copying to the lib's folder. I work with Oracle BRM
CFLAGS_solaris= -g -xcg92 -xprofile=tcov
C++FLAGS_solaris= -g -library=%none -DPIN_NOT_USING_OSTREAM
CPPFLAGS = -I$(INCDIR) -I$(INCDIR_MDS) -DPCMCPP_CONST_SAFE
LDFLAGS_solaris= -G
SL_EXT_solaris= so
and i tried also:
this makes the .so file;
$(LIBBILL): $(OBJECTS) $(C++_OBJECTS) $(INCFILES) Makefile
$(C++) -o $(LIBBILL) $(LDFLAGS) $(OBJECTS) $(C++_OBJECTS) -lm -lpsiu_for_cm -xprofile=tcov
and this makes the .o files
$(OBJECTS): $(INCFILES) Makefile $(FILES)
$(CC) -c $(CFLAGS) $(CPPFLAGS) $(FILES)
the result of that is the brm can't start.
If someone is looking for an answer I found the solution. You have to use
-xprofile=tcov while compiling .o files and also when you links .so file ;)

How do I include a path to libraries in g++

I am trying to include the path to extra libraries in my makefile, but I can't figure out how to get the compiler to use that path. so far I have:
g++ -g -Wall testing.cpp fileparameters.cpp main.cpp -o test
and I want to include the path to
/data[...]/lib
because testing.cpp includes files from that library. Also, I'm on a linux machine.
EDIT: Not a path to a library. Just to files that were included. My bad.
To specify a directory to search for (binary) libraries, you just use -L:
-L/data[...]/lib
To specify the actual library name, you use -l:
-lfoo # (links libfoo.a or libfoo.so)
To specify a directory to search for include files (different from libraries!) you use -I:
-I/data[...]/lib
So I think what you want is something like
g++ -g -Wall -I/data[...]/lib testing.cpp fileparameters.cpp main.cpp -o test
These compiler flags (amongst others) can also be found at the GNU GCC Command Options manual:
3.16 Options for Directory Search
In your MakeFile or CMakeLists.txt you can set CMAKE_CXX_FLAGS as below:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/path/to/your/folder")
Alternatively you could setup environment variables.
Suppose you are using bash, then in ~/.bashrc, write
C_INCLUDE_PATH="/data/.../lib/:$C_INCLUDE_PATH" ## for C compiler
CPLUS_INCLUDE_PATH="/data/.../lib/:$CPLUS_INCLUDE_PATH" ## for Cpp compiler
export C_INCLUDE_PATH
export CPLUS_INCLUDE_PATH
and source it with source ~/.bashrc.
You should be good to go.

Resources