Building C library (FFmpeg) with Android NDK r17: undefined reference to '__mulodi4' - ffmpeg

My problem happens to be with FFmpeg but I suspect that this would happen with almost any C library.
Problem Description
My app uses FFmpeg that is compiled with NDK r10e. I am trying to update everything to NDK r17, while also switching to clang, since Google prefers us to use that over gcc.
My first step is to just build FFmpeg.
To that end, I have used the make_standalone_toolchain.py script to create a stand-alone toolchain for the x86 architecture, like so:
make_standalone_toolchain.py --arch x86 --api 21 --install-dir ~/Development/ndk-toolchains/x86
Then I configure the FFmpeg build as follows:
TOOLCHAIN_DIR=~/Development/ndk-toolchains/x86
./configure \
--prefix=$(pwd)/android/x86 \
--cross-prefix=$TOOLCHAIN_DIR/bin/i686-linux-android- \
--target-os=android \
--arch=x86 \
--enable-cross-compile \
--disable-asm \
--toolchain=clang-usan \
--disable-stripping \
--extra-cflags="-m32" \
--sysroot=$TOOLCHAIN_DIR/sysroot/
And then I build it as follows:
make clean
make -j4
make install
Everything seems to compile fine, but I get several linker errors that all say the same thing:
undefined reference to '__mulodi4'
Solutions I've tried
1. Linking against libclang_rt.builtins*
I found a few places around the Web which suggested that this is caused by the fact that libgcc doesn't provide __mulodi4. A github user named sitsofe was nice enough to post a work-around here. However, I am sure where to find this libclang_rt.builtins-i686.a library. Here is what I was able to find in my standalone toolchain directory:
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-x86_64.a
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-i386.a
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-aarch64-android.a
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-mips64-android.a
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-x86_64-android.a
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-i686-android.a
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-arm-android.a
./lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-mips-android.a
The libclang_rt.builtins-i686-android.a library looks close but (I think) no cigar. When I try to link to it, I get the same error:
undefined reference to '__mulodi4'
Here is my new FFmpeg build config command:
./configure \
--prefix=$(pwd)/android/x86 \
--cross-prefix=$TOOLCHAIN_DIR/bin/i686-linux-android- \
--target-os=android \
--arch=x86 \
--enable-cross-compile \
--disable-asm \
--toolchain=clang-usan \
--disable-stripping \
--extra-cflags="-m32" \
--extra-ldflags="-L${TOOLCHAIN_DIR}/lib64/clang/6.0.2/lib/linux/libclang_rt.builtins-i686-android.a" \
--sysroot=$TOOLCHAIN_DIR/sysroot/
I checked with -v to make sure that this line was added to the linker flags, and it was. However, I have no idea if this library should even be expected to work, let alone whether I'm adding it to the linker flags correctly. In any case, what I'm doing here doesn't work.
2. Switching to a different sanitizer
Instead of using the undefined sanitizer, I tried switching to the address sanitizer. This is (frankly) a total stab in the dark, based on a vague mention of asan being available in r17 at Google I/O this week.
In this case, FFmpeg builds just fine!
However, when I try to pull FFmpeg into my test project (a simple AAR w/ C++ support, that just has one jni method that calls av_gettime(), I get a ton of linker errors:
Error:error: undefined reference to '__asan_option_detect_stack_use_after_return'
Error:error: undefined reference to '__asan_stack_malloc_0'
Error:error: undefined reference to '__asan_report_load4'
Error:error: undefined reference to '__asan_report_load4'
Error:error: undefined reference to '__asan_shadow_memory_dynamic_address'
Error:error: undefined reference to '__asan_option_detect_stack_use_after_return'
Error:error: undefined reference to '__asan_stack_malloc_0'
Error:error: undefined reference to '__asan_report_load4'
Error:error: undefined reference to '__asan_report_load4'
Error:error: undefined reference to '__asan_shadow_memory_dynamic_address'
Error:error: undefined reference to '__asan_option_detect_stack_use_after_return'
Error:error: undefined reference to '__asan_stack_malloc_0'
Error:error: undefined reference to '__asan_report_store4'
Error:error: undefined reference to '__asan_report_store4'
Error:error: undefined reference to '__asan_init'
Error:error: undefined reference to '__asan_version_mismatch_check_v9'
So it seems to find the FFmpeg library just fine, indicating that that part of my CMake file is correct, but it can't locate any of these asan references.
This seems to be a common problem that people are running into, but I can't see to find a work-around that actually works for me.

The short answer: update to NDK r17.
This is referred to in a handful of NDK bugs:
https://github.com/android-ndk/ndk/issues/184
https://github.com/android-ndk/ndk/issues/294 (the root cause, not the same symptom)
https://github.com/android-ndk/ndk/issues/506
Essentially Clang was generating calls that libgcc doesn't implement. I say was rather than is because this doesn't seem to be the case any more for NDK r17 for this specific function.
In the event that you're still hitting this and I just wasn't able to with any of the earlier test cases, you can try linking with -lcompiler_rt-extras. This is included as of NDK r17 and has the missing functions.

Related

GCC ICU 57 static linking

I am trying to link ICU 57 to my binary file. That does not work even thought (I think at least) I am linking the static lib files.
Here is a blunt example:
gcc -static /usr/lib/libicui18n.a /usr/lib/libicuuc.a /usr/lib/libicudata.a /usr/lib/libicule.a /usr/lib/libiculx.a /usr/lib/libicutu.a /usr/lib/libicuuc.a /usr/lib/libicuio.a obj/ex.o obj/msg.o -o bin/ex
This is the error message that I get:
src/msg.c:5: undefined reference to `u_fopen_57'
src/msg.c:9: undefined reference to `u_fgetfile_57'
src/msg.c:10: undefined reference to `u_fgetfile_57'
src/msg.c:11: undefined reference to `u_frewind_57'
src/msg.c:18: undefined reference to `u_fgetc_57'
src/msg.c:17: undefined reference to `u_feof_57'
src/msg.c:25: undefined reference to `u_fclose_57'
Linking the dynamic libs works fine though.
If you can, I'd recommend using pkg-config as I recommended here,
specifically with pkg-config --static … as explained here

Suricata luajit compilation error

I'm currently trying to compile suricata (http://suricata-ids.org/) with luajit support on my arch linux distribution with these commands:
./configure --enable-luajit --with-libpcap-includes=/usr/local/pfring/include \
--with-libpcap-libraries=/usr/local/pfring/lib --with-libnss-libraries=/usr/lib \
--with-libnss-includes=/usr/include/nss/ --with-libnspr-libraries=/usr/lib \
--with-libnspr-includes=/usr/include/nspr \
--with-libluajit-includes=/usr/local/include/luajit-2.0/ \
--with-libluajit-libraries=/usr/lib/
then:
make
but I get the following errors when I make the project:
detect-luajit.o: In function `LuaDumpStack':
detect-luajit.c:(.text+0x46e): undefined reference to `lua_tonumberx'
detect-luajit.o: In function `DetectLuajitMatchBuffer':
detect-luajit.c:(.text+0x5d6): undefined reference to `lua_getglobal'
detect-luajit.c:(.text+0x6b9): undefined reference to `lua_pcallk'
detect-luajit.c:(.text+0x7d5): undefined reference to `lua_tonumberx'
detect-luajit.o: In function `DetectLuajitMatch':
detect-luajit.c:(.text+0xaac): undefined reference to `lua_getglobal'
detect-luajit.c:(.text+0xde4): undefined reference to `lua_pcallk'
detect-luajit.c:(.text+0xf00): undefined reference to `lua_tonumberx'
detect-luajit.o: In function `DetectLuajitThreadInit':
detect-luajit.c:(.text+0x1864): undefined reference to `lua_pcallk'
detect-luajit.o: In function `DetectLuaSetupPrime':
detect-luajit.c:(.text+0x1fe7): undefined reference to `lua_pcallk'
detect-luajit.c:(.text+0x2167): undefined reference to `lua_getglobal'
detect-luajit.c:(.text+0x24bf): undefined reference to `lua_pcallk'
collect2: error: ld returned 1 exit status
make[2]: *** [suricata] Error 1
I first though it was an issue coming from the lua version. So I tried to install both the lua 5.1.5 and 5.2.2, remaking the library and symbolic links as well, and nothing worked.
Thanks for your help
In Debian and Ubuntu, the library files are installed into /usr/lib/x86_64-linux-gnu/. If arch does the same, your configure line should include: --with-libluajit-libraries=/usr/lib/x86_64-linux-gnu/

Problems Linking to libcuda.so

I am stumped by what seems to be a problem that should be easy to diagnose and fix. I have a C++ source file that makes use of the CUDA Driver API. When I compile it using nvcc, the executable is produced and works without problems. However, when I try to compile it using g++, the linker complains about undefined references to symbols that are in /usr/lib/libcuda.so:
undefined reference to cuDeviceGet'
... undefined reference tocuDeviceComputeCapability'
... undefined reference to cuDeviceGetName'
... undefined reference tocuDeviceTotalMem_v2'
... undefined reference to cuDeviceGetAttribute'
... undefined reference tocuDeviceGetAttribute'
... undefined reference to cuDeviceGetAttribute'
... undefined reference tocuDeviceGetAttribute'
I tried to ensure that /usr/lib is included in the library path (by supplying the flags -L/usr/lib, -lcuda, and adding /usr/lib to $LIBRARY_PATH). However, the problem still persists. I am sure that /usr/lib/libcuda.so contains the symbols that the linker is complaining about:
$ nm -D /usr/lib/libcuda.so | grep cuDeviceGet
00000000000be410 T cuDeviceGet
00000000000bf120 T cuDeviceGetAttribute
00000000000d2e10 T cuDeviceGetByPCIBusId
00000000000be200 T cuDeviceGetCount
00000000000bdfa0 T cuDeviceGetName
00000000000d2bb0 T cuDeviceGetPCIBusId
00000000000bf380 T cuDeviceGetProperties
I find it strange that nvcc successfully compiles the file, but g++ does not. Do you have any idea as to how I can fix this problem?
Thank you very much for your help!
Ok, the reason I was not able to compile the file was because the -lcuda flag has to come after the filename. Otherwise, it won't work... a large, prominent warning with the compiler telling me this information would have been much appreciated. Well, that was a waste of two hours.

gcc newly installed libraries (libexpat1-dev) not recognised in current terminal (debian)

I've spent quite a bit of time trying to get an expat based sample program to compile.
I was receiving the following error message when I tried to compile
gcc -Wall -lexpat line.c -o blah
line.c: In function ‘main’:
line.c:99:8: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘XML_Size’ [-Wformat]
/tmp/ccUa3vfD.o: In function `printcurrent':
line.c:(.text+0x42): undefined reference to `XML_SetDefaultHandler'
line.c:(.text+0x4d): undefined reference to `XML_DefaultCurrent'
line.c:(.text+0x60): undefined reference to `XML_SetDefaultHandler'
/tmp/ccUa3vfD.o: In function `main':
line.c:(.text+0x162): undefined reference to `XML_ParserCreate'
line.c:(.text+0x1ad): undefined reference to `XML_UseParserAsHandlerArg'
line.c:(.text+0x1c9): undefined reference to `XML_SetElementHandler'
line.c:(.text+0x1dd): undefined reference to `XML_SetCharacterDataHandler'
line.c:(.text+0x1f1): undefined reference to `XML_SetProcessingInstructionHandler'
line.c:(.text+0x2b2): undefined reference to `XML_Parse'
line.c:(.text+0x2c2): undefined reference to `XML_GetErrorCode'
line.c:(.text+0x2ca): undefined reference to `XML_ErrorString'
line.c:(.text+0x2d8): undefined reference to `XML_GetCurrentLineNumber'
collect2: ld returned 1 exit status
I had already run the following commands:
sudo apt-get install expat libexpat1 libexpat1-dev libxmltok1-dev
So I messed around for ages, trying to get the error message to go away so I could compile this (simple) little program, but to no avail.
Eventually, out of sheer randomness, I decided to switch to a Virtual Terminal.
I ran exactly the same command, this time it worked without a problem.
Can anyone tell me why this is? Is there something I need to run in order to refresh the library paths?
The linker line (i.e. the flags you give with -l and your input file names) are order-dependent. Libraries are only used to define functions used on their left side, but not on their right. Use:
gcc -Wall line.c -lexpat -o blah
See the question library is linked but reference is undefined for more information.

GSoap QT undefined reference to `soap_new'?

I'm trying to use gSoap in QT. When I compile my project I get:
undefined reference to `soap_new'
undefined reference to `soap_delete'
undefined reference to `soap_end'
undefined reference to `soap_free'
undefined reference to `soap_delete'
undefined reference to `soap_end'
undefined reference to `soap_free'
My sample pro contains:
INCLUDEPATH += ../../gsoap-2.8/gsoap/
LIBS += -lwsock32
Any idea what's wrong?
I produced file with:
soapcpp2 -I ../../gsoap-2.8/gsoap/import -i quote.h
soapcpp2 -I ../../gsoap-2.8/gsoap/import quote.h
Those functions are defined in sdtsoap2.c or stdsoap2.cpp (depending if you are using C or C++; for Qt I infer C++).
You must either include stdsoap2.cpp in your project or link against libsoap++.
If you need to pass different flags like WITH_NONAMESPACES, use the first.If you have no special configuration for GSOAP, use the later.
Look at GSOAP docs for more info.

Resources