Nonos
Nonos

Reputation: 2518

Shared library using static gnutls library has text relocations

Problem: I need to port gnutls to Android to be used in a shared library (say library A) I'm using in my Android application.

What I've tried: I've modified the make file for openconnect to generate a .a static library file for gnutls and its dependencies (libgmp, libnettle and libhogweed), I used them to build static libraries in my Android project and referenced them in the shared library A. Code builds and installs fine but on M+ devices I get the following error at runtime:

java.lang.UnsatisfiedLinkError: dlopen failed: libA.so: has text relocations

I've tried to pass the -fPIC flag when building the static libraries (.a files) and when building the libA.so file with no luck, I can always see TEXTREL entries in libA.so file. I'm sure it is due to the those new static libraries since I was using libA before with no issues. Other thing I tried: tried building gnutls as a shared library, the generated libA.so now had no text relocations but would still fail to load at runtime because the gnutls so files have a version (e.g libgnutls.so.3.0) and Android does not support versioned libraries.

Specific question: How can I either: 1.Build gnutls as a static library without text relocations or 2. Build it as a shared library with no soname?

Edit: I see the same question asked on the openconnect mailing list but no clear way on how to "fix the TEXTRELs in the native code first".

I have seen other answers for problems with text relocations like this question and this question but that didn't help since I'm using the latest NDK build and passing the PIC flag already

Upvotes: 3

Views: 2021

Answers (2)

Nonos
Nonos

Reputation: 2518

I finally figured it out. Since gnutls depends on nettle and gmp while nettle depends on gmp as well I had to build gmp as a shared library and the rest as static. Since libgmp was the only one building without sonames I had no problem to build it this way. So this is my final Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libgmp
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libgmp.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libhogweed
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libhogweed.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libnettle
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libnettle.a
LOCAL_SHARED_LIBRARIES := libgmp
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := libgnutls
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libgnutls.a
LOCAL_SHARED_LIBRARIES := libgmp
LOCAL_STATIC_LIBRARIES := libhogweed libnettle
include $(PREBUILT_STATIC_LIBRARY)

Upvotes: 0

Shmuel H.
Shmuel H.

Reputation: 2546

You can't load a library that requires Text Relocations:

Starting with API 23, shared objects must not contain text relocations. That is, the code must be loaded as is and must not be modified.

(source)

Answers:

How can I build gnutls as a static library without text relocations?

-fPIC can't prevent all text relocation. In some cases, if your library uses inline asm, the compiler will unable to make it Position Independent (PIC). However, if you sure your library can be position independent, the problem may be a somewhere in your build config.

If not, you should prevent your library from using text Relocations. Fortunately, there is a great wiki page that explains how to do that in the Gentoo Wiki.

How can I build it as a shared library with no soname?

You can set your soname with: gcc -shared -Wl,-soname,your_soname.

Upvotes: 1

Related Questions