I'm trying to compile a simple JNI application on an embedded Linux platform (a GuruPlug computer), but for some reason it's not linking to libc properly. The Java program I'm compiling is called Test.java:
public class Test {
static {
System.loadLibrary("Test");
}
public static void main(String[] args) {
new Test().printMessage();
}
public native void printMessage();
}
The implementation of printMessage() is in Test.c:
#include <jni.h>
#include <stdio.h>
#include "Test.h"
JNIEXPORT void JNICALL Java_Test_printMessage(JNIEnv *env, jobject obj)
{
printf("Message 123...\n");
}
I'm compiling Test.c with the following command on a bash shell:
gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so
When I run the above command, I get the error message "R_ARM_TLS_LE32 relocation not permitted in shared object". The full error message is:
/usr/bin/ld: /usr/lib/gcc/arm-linux-gnueabi/4.4.5/../../../libc.a(dl-tsd.o)(.text+0x18): R_ARM_TLS_LE32 relocation not permitted in shared object
Despite the error message, the JNI .so file is still written by the compiler, but running the Java application gives the following error message:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /usr/lib/jni/libTest.so: /usr/lib/jni/libTest.so: unexpected reloc type 0x03
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1750)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1675)
at java.lang.Runtime.loadLibrary0(Runtime.java:840)
at java.lang.System.loadLibrary(System.java:1047)
at Test.<clinit>(Test.java:3)
Could not find the main class: Test. Program will exit.
Does anybody have any idea how to go about fixing this? Admittedly, the above code is a toy example, but I need to get a real JNI library compiling on this platform, and the real JNI library depends on libc. I can't seem to solve this basic issue of linking libc with a JNI library. Any suggestions would be greatly appreciated.
Thanks!
gcc -g -shared -static -lc -Wl,-soname,libTest.so -I${JAVA_HOME}/include/ -I${JAVA_HOME}/include/linux/ Test.c -o libTest.so
There are several problems with the command line above:
the -shared and -static flags are mutually exclusive, and the second overrides the first
when linking shared libraries, you want -fPIC on most architectures
the -lc is in the wrong place (should follow your sources, not precede them), and is not necessary anyway: gcc will add it automatically
you don't strictly need the -soname either; it's just useless clutter
The correct command then is:
gcc -g -shared -fPIC -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux \
Test.c -o libTest.so
Related
In a directory I have a C file and its header
/home/test/c_pro
f.c
f.h
libf.so
I have compiled the f.c into a dll called libf.so using the following command
gcc -c -fPIC f.c -o f.o
gcc f.o -shared -o f.so
I want to use this in my Rust project.
So in Rust project I have a build.rs
println!("cargo:rustc-link-search=/home/test/c_pro");
println!("cargo:rustc-link-lib=dylib=f")
When I run a cargo build the build fails with the following errors
/home/test/c_pro/f.so: undefined reference to `EC_KEY_new_by_curve_name'
collect2: error: ld returned 1 exit status
In my f.c I do some imports from openssl
#include <openssl/bio.h>
#include <openssl/bn.h>
#include <openssl/ecdsa.h>
#include <openssl/obj_mac.h>
and use symbols from these libraries.
Any ideas as to why the build fails? I am following the official doc and am relying on 2 build parameters
cargo:rustc-link-search so that cargo can know that he has to do a look up in this directory as well.
cargo:rustc-link-lib=dylib to tell what dynamic library to link to.
What am I missing here folks?
Thanks in advance.
EDIT+UPDATE:
I did as pointed out by #Uli Schlachter and it compiles but I get a runtime error stating that libf.so is not found.
ldd ./target/debug/test_f
libf.so => not found.
Any ideas?
Compile your shared object with
gcc -c -fPIC f.c -o f.o
gcc f.o -shared -o f.so -lssl
I'm trying to build a stand-alone binary containing a Rest API made with pistache framework. For that purpose I created a docker image using "FROM i386/ubuntu:16.04" and installing all dependencies in it. But the binary throws "Segmentation fault" error when I try to execute it and it's compilation shows some warnings.
I compile it with this command (output warnings included):
g++ server.cpp -std=c++11 -lpistache -lssl -lcrypto -pthread -ldl -static -o server
root#91cb986a4e48:/workspace# g++ server.cpp -std=c++11 -lpistache -lssl -lcrypto -pthread -ldl -static -o server
/usr/lib/gcc/i686-linux-gnu/5/../../../i386-linux-gnu/libcrypto.a(dso_dlfcn.o): In function `dlfcn_globallookup':
(.text+0xa): warning: Using 'dlopen' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
//usr/local/lib/libpistache.a(listener.cc.o): In function `Pistache::Tcp::Listener::bind(Pistache::Address const&)':
listener.cc:(.text+0x1b94): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
//usr/local/lib/libpistache.a(net.cc.o): In function `Pistache::Address::init(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
net.cc:(.text+0x14ce): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
server.cpp contains the hello world code from pistache:
#include <pistache/endpoint.h>
using namespace Pistache;
struct HelloHandler : public Http::Handler {
HTTP_PROTOTYPE(HelloHandler)
void onRequest(const Http::Request&, Http::ResponseWriter writer) override{
writer.send(Http::Code::Ok, "Hello, World!");
}
};
int main() {
Http::listenAndServe<HelloHandler>("*:9080");
}
When I compile and run it in my pc there is no problem (compiling with "g++ server.cpp -std=c++11 -lpistache -o server"), but how can I make it work in my i686 board?
I was trying this on my 64 bit ubuntu:
First I've got a simple program
$ cat test.c
int f(int x){
int i=(x/42);
return i;
}
int main(){
return 0;
}
Then I manually specify how it's linked:
$ gcc test.c -nostdlib /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o
I got some errors:
/usr/lib/x86_64-linux-gnu/crt1.o:In function ‘_start’中:
(.text+0x12):unresolved reference to ‘__libc_csu_fini’
/usr/lib/x86_64-linux-gnu/crt1.o:In function ‘_start’:
(.text+0x19): unresolved reference to ‘__libc_csu_init’
/usr/lib/x86_64-linux-gnu/crt1.o:In function ‘_start’:
(.text+0x25): unresolved reference to ‘__libc_start_main’
collect2: error: ld returned 1 exit status
I was trying to see how gcc deals with all necessary object files and try to do it manually. How to fix it? Thanks.
How to fix it?
You are missing libc symbols, so you need to link libc:
gcc test.c -nostdlib /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o -lc
Bear in mind that if you really want to link something "manually", you will do it with ld, not gcc
I have just installed gcc 4.8.2 on Centos (I am using devtoolset-2). I wrote a very simple program using thread. It compiles fine but crashes when executed?
#include <thread>
#include <iostream>
void test()
{
std::cout << "test\n";
}
void main()
{
std::thread t(test);
t.join();
return 0;
}
I compile with:
scl enable devtoolset-2 bash
c++ -o test test.cpp -std=c++11
I am terribly surprised. I must do something wrong, not using the write libc++ etc? Do you have any idea how I could debug this. Thank you!
I compile it on Mac (Maverick) which obviously doesn't use gcc and it works fine.
On Linux, you should use the command line option -pthread with GCC and Clang for compiling and linking. In your case, the command line should look as follows:
g++ -std=c++11 -Wall -Wextra -pthread test.cpp -o test
See the following links for more information:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_concurrency.html
gcc - significance of -pthread flag when compiling
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52681
My application uses my shared library. Application and library must be mudflapped to check out of bounds reads and writes both on stack and heap. Shared library was successfully build, but while linking application I had a lot of errors.
I made a simple example that reproduces this issue. Here are steps to reproduce:
create C++ dynamic shared library project with 2 files: h and cpp files with some class, and in h or cpp file use #include <iostream>
create C++ application that uses this library (uses class from inside shared library)
build library
build application (here you will catch an linking error)
Here are my files:
SharedLibTest.h
#ifndef SHAREDLIBTEST_H_
#define SHAREDLIBTEST_H_
#include <iostream>
class SharedLibTest {
public:
void func();
};
#endif /* SHAREDLIBTEST_H_ */
SharedLibTest.cpp
#include "SharedLibTest.h"
void SharedLibTest::func()
{}
main.cpp
#include <SharedLibTest.h>
int main(int argc, char *argv[])
{
SharedLibTest obj;
obj.func();
return 0;
}
Building the library:
g++ -O0 -g3 -Wall -c -fmessage-length=0 -fmudflap -funwind-tables -fPIC -MMD -MP -MF"SharedLibTest.d" -MT"SharedLibTest.d" -o "SharedLibTest.o" "../SharedLibTest.cpp"
g++ -rdynamic -shared -o "libshared_lib.so" ./SharedLibTest.o -lmudflap
Building the application:
g++ -I"/home/msviridov/work/prj/workspace/shared_lib" -O0 -g3 -Wall -c -fmessage-length=0 -fmudflap -funwind-tables -MMD -MP -MF"main.d" -MT"main.d" -o "main.o" "../main.cpp"
g++ -L"/home/msviridov/work/prj/workspace/shared_lib/Debug" -rdynamic -v -o "executable" ./main.o -lshared_lib -lmudflap
Linker error output is:
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<unsigned long>::__digits'
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<long>::__min'
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<short>::__min'
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<char>::__max'
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<short>::__max'
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<long>::__max'
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<int>::__max'
/home/msviridov/work/prj/workspace/shared_lib/Debug/libshared_lib.so: undefined reference to `__gnu_cxx::__numeric_traits_integer<int>::__min'
collect2: ld returned 1 exit status
make: *** [executable] Error 1
Though, if I remove mudflap compiler and linker flags for library the build of application will finish successfully.
But it's not true for vice versa.
I don't understand what does lead to such result.
My platform is Linux Mint 13 Maya 64 bit. I'll appreciate any help. Thanks.
Remove #include <iostream> from your header file. If you want to include iostream do that in your source (SharedLibTest.cpp) file.
Including it in header file also includes lots of garbage for you and also may cause some reference errors like this. Create SharedLibTest.o without that include and compare the sizes of object files.
You are probably hitting bug 53359 but you'd need recent 4.8 code to check. Furthermore, be advised that mudflap is for C and very simple C++ programs so you may find false possitives (ala bug 19319) and it doesn't work with DSOs yet.