clang-3.8 and compiler-rt vs libgcc - clang

I have been using clang-3.5 to happily build bitcode versions of musl libc and
use the result to produce nice stand alone executables.
Recent attempts with clang-3.8 have not been so happy. It seems that
the bitcode clang-3.8 generates uses functions defined in
compiler-rt/lib/builtins
Typical examples of functions I find polluting the bitcode are mulxc3, mulsc3, and muldc3. I can solve this by linking against libgcc, or even the llvm alternative if I had any clear idea of what that was. Though I would rather prevent the problem from happening in the first place.
I have seen mention of flags like rtlib=compiler-rt etc, but have found precious little documentation on the subject.
So here are some simple questions.
Is it possible to prevent clang from using the compiler-rt/lib/builtins
in the emitted bitcode? Or if not
Does llvm produce a version of libgcc that I could use. Actually I would
probably build a bitcode version of it, but that is besides the point.
Love to hear some guidance on this.
Added 12/8/2016: So I will illustrate my issues with a particular workflow that
people can reproduce if they wish, or, more likely, just point out where I am being stupid.
So start by checking out:
musllv
and follow the instructions in the README.to compile (here I am using clang-3.8 on ubuntu 14.04)
WLLVM_CONFIGURE_ONLY=1 CC=wllvm ./configure --target=LLVM --build=LLVM
make
cd lib
extract-bc -b libc.a
you will also need the bitcode of a simple executable. I will use nweb.c here.
wllvm nweb.c -o nweb
extract-bc nweb
Now we can do things like:
clang -static -nostdlib nweb.bc libc.a.bc crt1.o libc.a -o nweb
This workflow goes smoothly for clang-3.5 but for clang-3.8 we get:
clang -static -nostdlib nweb.bc libc.a.bc crt1.o libc.a -o nweb
/tmp/libc-f734a3.o: In function `cpowl':
libc.a.bc:(.text+0xbb9a): undefined reference to `__mulxc3'
/tmp/libc-f734a3.o: In function `cpowf':
libc.a.bc:(.text+0x38f7d): undefined reference to `__mulsc3'
/tmp/libc-f734a3.o: In function `csqrt':
libc.a.bc:(.text+0x78fc3): undefined reference to `__muldc3'
/tmp/libc-f734a3.o: In function `cpow':
libc.a.bc:(.text+0xafafc): undefined reference to `__muldc3'
clang-3.8: error: linker command failed with exit code 1 (use -v to seeinvocation)
So as #paul-brannan points out we could try
clang -static -nostdlib --rtlib=compiler-rt nweb.bc libc.a.bc crt1.o libc.a -o nweb
But this is where I am probably being stupid, because I get:
clang-3.8: warning: argument unused during compilation: '--rtlib=compiler-rt'
irregardless of whether I use it as a linking or compiling flag.

OK so I finally managed to make headway on this. I built llvm-3.8.1 together with the compiler-rt project using wllvm and wllvm++.
One of the build products was libclang_rt.builtins-x86_64.a,
and from this archive I was able to extract the bitcode module
libclang_rt.builtins-x86_64.bc
using the command:
extract-bc -b libclang_rt.builtins-x86_64.a
This bitcode module has definitions for those pesky instrinsics like
__mulxc3, __mulsc3, and __muldc3.
Hallelujah!

Related

Using Clang with built libstdc++ produces undefined symbol _ZSt15__once_callable

I have built libstdc++ with no modifications yet:
cd gccsrcdir/libstdc++-v3/build
../configure --prefix=$PWD/../install
make && make install
I am using Ubuntu 21.10 and I set the following environment variables:
export LIBRARY_PATH=gccsrcdir/libstdc++-v3/install/lib
export LD_LIBRARY_PATH=gccsrcdir/libstdc++-v3/install/lib
export CPLUS_INCLUDE_PATH=gccsrcdir/libstdc++-v3/install/include/c++/13.0.0
When I then use the system's GCC, I get no problems. When I use the system's Clang, it produces a symbol lookup error - even with no parameters:
clang++
clang++: symbol lookup error: /lib/x86_64-linux-gnu/libicuuc.so.67: undefined symbol: _ZSt15__once_callable, version GLIBCXX_3.4.11
In fact I only need to update LD_LIBRARY_PATH to arrive here. What am I doing wrong?
The symbol -- std::__once_callable is defined in your system libstdc++.so.6 (it has version GLIBCXX_3.4.11 in my build, which means it was added in GCC-4.4.0).
Your build of libstdc++.so.6 should define this symbol as well, but for some reason does not. That is a problem -- any binary which uses this symbol will fail at runtime when using your build of libstdc++.so.6 (which is happening because you've pointed LD_LIBRARY_PATH to it).
Note: in your case it's the clang++ binary that is failing to run -- any flags you add to it (such as -femulated-tls) are irrelevant -- they only affect the binary that would have been generated IF clang++ itself didn't fail.
I just repeated your configure && make steps, and the library built this way also doesn't define this symbol.
I then repeated the configure && make, but starting from top-level GCC directory, and libstdc++.so.6 built that way does define the symbol.
Conclusion: libstdc++ is configured differently during "normal" GCC build.
The definition comes from mutex.o, which is built from ./libstdc++-v3/src/c++11/mutex.cc, and which has this chunk of code:
#ifdef _GLIBCXX_HAS_GTHREADS
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#ifdef _GLIBCXX_HAVE_TLS
__thread void* __once_callable;
__thread void (*__once_call)();
...
So it sounds like either _GLIBCXX_HAS_GTHREADS or _GLIBCXX_HAVE_TLS is not defined when doing configure && make in the libstdc++-v3 directly.
Digging further, I see that libstdc++-v3 determines _GLIBCXX_HAS_GTHREADS by trying to compile #include "gthr.h", and that file is available in libgcc/gthr.h, but not in "standard" installed GCC.
../libstdc++-v3/configure && grep _GLIBCXX_HAS_GTHREADS config.h
/* #undef _GLIBCXX_HAS_GTHREADS */
TL;DR: correctly configuring libstdc++.so is complicated, and you will be better off building complete GCC.
Once you have a complete build, you will have a libstdc++-v3 directory properly configured, and can just rebuilt in that directory:
grep _GLIBCXX_HAS_GTHREADS ./x86_64-pc-linux-gnu/libstdc++-v3/config.h
#define _GLIBCXX_HAS_GTHREADS 1

ld cannot find OCCI libraries even if they exist in LD_LIBRARY_PATH

I am just doing some simple OCCI thing, however it compiles a bit strangely
Environment:
Oracle VM: Centos7 64bit on Windows 8 64bit
gcc-c++.x86_64
Simply installed Oracle XE by double clicking the rpm (download pages says
linux 64bit)
echo $LD_LIBRARY_PATH yields:
/usr/local/lib64/:/u01/app/oracle/product/11.2.0/xe/lib/
I also tried export LD_LIBRARY_PATH=/u01/app/oracle/product/11.2.0/xe/lib/
so that it yields
/u01/app/oracle/product/11.2.0/xe/lib/
some listing command:
find /u01/app/oracle/product/11.2.0/xe/lib/ -name lib*
yields the following:
/u01/app/oracle/product/11.2.0/xe/lib/
/u01/app/oracle/product/11.2.0/xe/lib/libagtsh.so.1.0
/u01/app/oracle/product/11.2.0/xe/lib/libcell11.so
/u01/app/oracle/product/11.2.0/xe/lib/libclntsh.so.11.1
/u01/app/oracle/product/11.2.0/xe/lib/libnnz11.so
/u01/app/oracle/product/11.2.0/xe/lib/libocci.so.11.1
/u01/app/oracle/product/11.2.0/xe/lib/libclntsh.so
/u01/app/oracle/product/11.2.0/xe/lib/libocci.so
/u01/app/oracle/product/11.2.0/xe/lib/libagtsh.so
and some others....
however the compile command says ld cannot find some libraries:
g++ -o ab -I/u01/app/oracle/product/11.2.0/xe/rdbms/public/ -lnnz11 -lclntsh -locci a.cpp
/usr/bin/ld: cannot find -lnnz11
/usr/bin/ld: cannot find -lclntsh
/usr/bin/ld: cannot find -locci
collect2: error: ld returned 1 exit status
I have tried adding -L/u01/app/oracle/product/11.2.0/xe/lib/, it successfully compiles however running the program will cause it silently crashes / blocks at the simple line
Environment *env = Environment::createEnvironment();
no exceptions caught.
Does anyone know some part I did wrong? or are the two issues related?
And by the way, it USED to work like 5 hours ago, when it suddenly stopped working I reinstalled the whole VM and now it still doesn't work.
however the compile command says ld cannot find some libraries: g++ -o ab -I/u01/app/oracle/product/11.2.0/xe/rdbms/public/ -lnnz11 -lclntsh -locci a.cpp
Your command is incorrect (and the linker is right to complain). You need to tell the linker where to find the library, and you do that with -L flag:
ORACLE=/u01/app/oracle/product/11.2.0/xe
g++ -I ${ORACLE}/rdbms/public -L ${ORACLE}/lib a.cpp -lnnz11 -lclntsh -locci
(Note that your placement of source after library is also incorrect, and I fixed it above. Placement of libraries and sources on link command line matters.)

Enabling the gold linker on Freebsd

I have been trying to enable the gold linker on FreeBSD to use the link time optimizations. I made gold from the binutils under /usr/ports. After building binutils using make -k install clean i got ld under /usr/bin and in the directory /usr/local/bin i got ld, ld.gold and ld.bfd.
Now while trying to use link time optimization for the simple example programs here http://llvm.org/docs/GoldPlugin.html (a.c and b.c under the heading 'Examples of Link Time Optimization') i entered the four commands as follows:
clang -flto a.c -c -o a.o
ar q a.a a.o
clang b.c -c -o b.o
clang -flto a.a b.o -o main
I got the following error:
usr/bin/ld: unrecogonized option '-plugin'
usr/bin/ld: use the --help option for usage information
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Is there the problem with the linker that ld.gold is not being called. Should I replace the ld with ld.gold? Does the linker looks in the right directiry for the .so plugins?
The LLVMgold.so and libLTO.so shared objects are in the directory /usr/local/llvm-devel/lib/.
I cannot find the directory where clang is installed. I am not sure where to make the bfd-plugins directory and add the symlinks to LLVMgold.so and libLTO.so.
I am using freebsd 10.1 release. How to enable the gold linker for link time optimizations?
also how can I enable it to be the default linker?
You may want to use ld.gold instead of ld. It is installed at /usr/local/bin/ld.gold. If you are using a Makefile, it would work by setting LD variable to ld.gold, either by modifying your Makefile or specifying it on command line. Example in case you are using lang/clang37:
gmake all CC=clang37 LD=ld.gold
EDIT:
It would be even more neat if you add -fuse-ld=gold to your LDFLAGS:
LDFLAGS=-fuse-ld=gold
I'm not sure ld.bfd allows plugins, but I could be wrong.
Your /usr/bin/ld should be a symlink to whatever linker you want. You can change which linker is used by using binutils-config. Check the man-page here: http://www.linuxhowtos.org/manpages/8/binutils-config.htm. I realise this is a Linux link, but it's directed at binutils itself rather than linux-specifically.
It should be something along the lines binutils-config --gold.
On my Gentoo box it is binutils --linker=gold
EDIT: As pointed out, binutils-config doesn't work on BSD it seems. You can still manually update the symlinks though, the downside is that there might be a few of them.
You can find out which ld is used by your compiler by using gcc -print-prog-name=ld or clang -print-prog-name=ld. The file printed should be a symlink you can re-create to point to ld.gold as oposed to ld.bfd.

LLVM bug building synthetic CPU for nostalgic childhood game (register asm global variable)

I've been trying to compile syn64k--for use in Executor, to run System's Twilight (a game I played as a kid). I'm doing this on my macbook pro (lion 10.7.4 with the latest Xcode and command line tools). I mapped CC to gcc -m32 to fix a couple problems I was having, but I got the following:
Making all in native/i386
make[2]: Nothing to be done for `all'.
outgoing=;\
gcc -m32 -maccumulate-outgoing-args -c -x c /dev/null 2> /dev/null && outgoing=-maccumulate-outgoing-args; \
gcc -m32 -S -O2 -fomit-frame-pointer -Wall -static -fno-defer-pop -Wno-unused\ -I./include -I./../include -I. -I../include $outgoing syn68k.c -o ./syn68k.s
syn68k.c: In function ‘s68k_handle_opcode_0x07A3’:
syn68k.c:52968: internal compiler error: in EmitLV_DECL, at llvm-convert.cpp:7475
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://developer.apple.com/bugreporter> for instructions.
make[2]: *** [syn68k.o] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all-recursive] Error 1
I went to URL, and it doesn't look like a place to really put a bug report about LLVM. I the file 'syn68k.c' is about 50k lines long after the preprocessor is done with it, so I really don't thing I can make a reproducible test case to show the bug.
Turns out this issue is already on the github project (it is the only issue listed, ha). MaddTheSane says that this happens because clang does not support global register variables (as I verified here).
I don't really have much more than a basic understanding of how compilation works after you type make, so is there a way I can skip clang or something like that? What do you suggest?
Unfortunately, you need to use gcc, not llvm-gcc to compile this program. The LLVM backend of llvm-gcc does not support global register variables. Switching to clang won't help because it too will choke on the global register variables, for the same reason.
you definitely can skip building clang if its not necessary for what using llvm for.
llvm uses cmake for configuration and the generation of makefiles. you can modify the .cmake files to create a configuration that disables any modules you don't want to create.
http://developer.apple.com/bugreporter is definitely the right place to report a bug against any compiler distributed by Apple, even if it may not look like it. That said, there's no point to filing a bug report against anything other than clang. (BTW, the size of the testcase doesn't really matter.)
If you don't know enough C to hack the source code, it might be worth a shot to grab a newer version of gcc from macports or something like that.

How to add directories to ld search path for a cross-compilation to ARM?

I am trying to configure util-linux to cross compile using arm-none-linux-gnueabi from CodeSourcery. My only problem so far is that it can't find my ncurses library which I compiled.
How can I add a directory to the ld search path? I've tried adding to my LIBRARY_PATH and LD_LIBRARY_PATH variables, but neither does anything. I know that I can add the -L flag to gcc and it will add to the linker path, but is there any way to do this globally, so that I can do it once, and not have to worry about it again?
Here is the output of arm-none-linux-gnueabi-gcc -print-search-dirs | grep libraries | sed 's/:/\n/g':
libraries
=/tools/bin/../lib/gcc/arm-none-linux-gnueabi/4.6.1/
/tools/bin/../lib/gcc/
/tools/bin/../lib/gcc/arm-none-linux-gnueabi/4.6.1/../../../../arm-none-linux-gnueabi/lib/arm-none-linux-gnueabi/4.6.1/
/tools/bin/../lib/gcc/arm-none-linux-gnueabi/4.6.1/../../../../arm-none-linux-gnueabi/lib/
/tools/bin/../arm-none-linux-gnueabi/libc/lib/arm-none-linux-gnueabi/4.6.1/
/tools/bin/../arm-none-linux-gnueabi/libc/lib/
/tools/bin/../arm-none-linux-gnueabi/libc/usr/lib/arm-none-linux-gnueabi/4.6.1/
/tools/bin/../arm-none-linux-gnueabi/libc/usr/lib/
I would like to add /arm/usr/lib and /arm/usr/local/lib to my ld search path.
If you need output from any other commands, just ask!
EDIT: I just found out about the CFLAGS environment variable--do all configure scripts/makefiles honor it?
Thank you!
If the ncurses library you compiled are going to be linked to the ARM binary you are cross-compiling you can not use LD_LIBRARY_PATH! LD_LIBRARY_PATH is only used by the current run-time and is in no way used by the compiler or linker when building your application.
The use of CFLAGS depends on creator of Makefile. CFLAGS are not automatically used even if they are defined as an environment variable. Only tools like the autoconf tools can pick them up from the environment and use them automagically. In the Makefiles find something like:
$(CC) $(CFLAGS) ....
if this fragment exists then the Makefile uses the CFLAGS variable. LDFLAGS is the more appropriate environment variable to use for link-time options.

Resources