Search code examples
mysqlshared-librariesrakeuser-defined-functionsudf

error building UDF mysql:relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC


I'm trying to build a UDF library using rake:

task :compile do
    system("gcc -L/usr/local/lib -lgmp -lpaillier `mysql_config --cflags` -c -fPIC #{FILE}.c")
    system("ar -x /usr/local/lib/libpaillier.a")
    system("gcc -shared *.o -L/usr/lib/x86_64-linux-gnu/ -lgmp -o #{LIBFILE}")
    system("sudo mv #{LIBFILE} /usr/lib/mysql/plugin/")
end

but I'm getting this error:

/usr/bin/ld: paillier.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
paillier.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

Solution

  • Here:

    gcc -L/usr/local/lib -lgmp -lpaillier `mysql_config --cflags` -c -fPIC #{FILE}.c
    

    you are compiling an object file whose name will be the value of #{FILE}.o - let's say it is aa.o - and you are compiling it with Position-Independent Code (-fPIC). Your linker flags:

    -L/usr/local/lib -lgmp -lpaillier
    

    serve no purpose here and are ignored because no linking is being done.

    Here:

    ar -x /usr/local/lib/libpaillier.a
    

    you are extracting all of the object files from the static library /usr/local/lib/libpaillier.a. There is in fact just one object file in the library, paillier.o

    Here:

    gcc -shared *.o -L/usr/lib/x86_64-linux-gnu/ -lgmp -o #{LIBFILE}
    

    you are building a shared library whose name will be the value of #{LIBFILE} - let's say it is libfoo.so - linking the object files aa.o, paillier.o, plus libgmp.

    Extracting the object file paillier.o from libpaillier.a to link it with libfoo.so achieves nothing different from not extracting it and simply linking libpaillier.a itself, i.e nothing different from:

    gcc -shared #{FILE}.o -L/usr/local/lib -lpaillier -L/usr/lib/x86_64-linux-gnu/ -lgmp -o #{LIBFILE}
    

    And the linkage library paths:

    -L/usr/local/lib -L/usr/lib/x86_64-linux-gnu/
    

    are superflous because both of those paths are default linker search paths on your system.

    But a shared library must be built entirely from PIC object code. aa.o was compiled with -fPIC, in your first step. However, paillier.o was not not. So the linkage fails and the linker advises you that paillier.o must be recompiled with -fPIC.

    So do that:-

    Delete your existing /usr/local/lib/libpaillier.a and /usr/local/include/paillier.h

    Go back to your libpaillier source directory (where you built it first time).

    Clean it up:

    $ make clean
    

    Reconfigure the autotools build system to compile PIC code:

    $ ./configure CFLAGS=-fPIC [and whatever other options you used before]
    

    Rebuild:

    $ make
    

    Reinstall:

    $ sudo make install
    

    Now you again have a header /usr/local/include/paillier.h and a static library /usr/local/lib/libpaillier.a but this time the paillier.o in the library is PIC code.

    Then you can build your plugin with:

    task :compile do
        system("gcc `mysql_config --cflags` -c -fPIC #{FILE}.c")
        system("gcc -shared #{FILE}.o -lpaillier -lgmp -o #{LIBFILE}")
        system("sudo mv #{LIBFILE} /usr/lib/mysql/plugin/")
    end