jedisct1 / libsodium

A modern, portable, easy to use crypto library.
https://libsodium.org
Other
12.22k stars 1.74k forks source link

relocation R_386_PC32 cannot be used against symbol crypto_hash_sha256_update; recompile with -fPIC #1047

Closed ghazel closed 3 years ago

ghazel commented 3 years ago

Attempting to use libsodium as a static library gives a linker error on the latest Android NDK (22.1.7171670).

An example command which generates the error:

~/libsodium# $ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin/i686-linux-android19-clang -fPIC -shared -o libtest.o -I test/default -I test/quirks -I libsodium-android-i686/include test/default/hash.c libsodium-android-i686/lib/libsodium.a
ld: error: relocation R_386_PC32 cannot be used against symbol crypto_hash_sha256_update; recompile with -fPIC
>>> defined in libsodium-android-i686/lib/libsodium.a(libsodium_la-hash_sha256_cp.o)
>>> referenced by hash_sha256_cp.c
>>>               libsodium_la-hash_sha256_cp.o:(crypto_hash_sha256) in archive libsodium-android-i686/lib/libsodium.a

ld: error: relocation R_386_PC32 cannot be used against symbol crypto_hash_sha256_final; recompile with -fPIC
>>> defined in libsodium-android-i686/lib/libsodium.a(libsodium_la-hash_sha256_cp.o)
>>> referenced by hash_sha256_cp.c
>>>               libsodium_la-hash_sha256_cp.o:(crypto_hash_sha256) in archive libsodium-android-i686/lib/libsodium.a

ld: error: relocation R_386_PC32 cannot be used against symbol crypto_hash_sha512_update; recompile with -fPIC
>>> defined in libsodium-android-i686/lib/libsodium.a(libsodium_la-hash_sha512_cp.o)
>>> referenced by hash_sha512_cp.c
>>>               libsodium_la-hash_sha512_cp.o:(crypto_hash_sha512) in archive libsodium-android-i686/lib/libsodium.a

ld: error: relocation R_386_PC32 cannot be used against symbol crypto_hash_sha512_final; recompile with -fPIC
>>> defined in libsodium-android-i686/lib/libsodium.a(libsodium_la-hash_sha512_cp.o)
>>> referenced by hash_sha512_cp.c
>>>               libsodium_la-hash_sha512_cp.o:(crypto_hash_sha512) in archive libsodium-android-i686/lib/libsodium.a

ld: error: relocation R_386_PC32 cannot be used against symbol sodium_malloc; recompile with -fPIC
>>> defined in libsodium-android-i686/lib/libsodium.a(libsodium_la-utils.o)
>>> referenced by utils.c
>>>               libsodium_la-utils.o:(sodium_allocarray) in archive libsodium-android-i686/lib/libsodium.a

ld: error: relocation R_386_PC32 cannot be used against symbol sodium_memcmp; recompile with -fPIC
>>> defined in libsodium-android-i686/lib/libsodium.a(libsodium_la-utils.o)
>>> referenced by utils.c
>>>               libsodium_la-utils.o:(sodium_free) in archive libsodium-android-i686/lib/libsodium.a

ld: error: relocation R_386_PC32 cannot be used against symbol sodium_munlock; recompile with -fPIC
>>> defined in libsodium-android-i686/lib/libsodium.a(libsodium_la-utils.o)
>>> referenced by utils.c
>>>               libsodium_la-utils.o:(sodium_free) in archive libsodium-android-i686/lib/libsodium.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)

libsodium was built with ./dist-build/android-x86.sh on revision d3f4804f4d4e6b5b4610fe377f6ff24e4368ae09 of the stable branch.

jedisct1 commented 3 years ago

Hi,

Unfortunately, I wasn't able to reproduce this on a cleanroom environment.

Standard installation of the NDK with Homebrew.

android-ndk: 21
https://developer.android.com/ndk/index.html
/usr/local/Caskroom/android-ndk/21 (10,084 files, 3.3GB)

Then I just did export ANDROID_NDK_HOME="/usr/local/share/android-ndk" and ./dist-build/android-x86.sh.

ghazel commented 3 years ago

Right, the error started with the release of android-ndk 22. Homebrew is behind.

jedisct1 commented 3 years ago

Oh, indeed. The version installed by Homebrew seems to be an LTS version.

Do you have an idea how to fix this?

jedisct1 commented 3 years ago

Wasn't able to reproduce with android-ndk-r22b and android-ndk-r23-beta2 either.

ghazel commented 3 years ago

Did you force it to rebuild the standalone toolchain?

jedisct1 commented 3 years ago

I have no idea what that means :)

I didn't do anything besides setting the environment variable and running the script.

jedisct1 commented 3 years ago

Works on Linux and on CI as well.

ghazel commented 3 years ago

I don't like docker, so I apologize for that, but to avoid setup / test differences here's a docker file that reproduces the issue:

FROM ubuntu:20.04

ENV ANDROID_NDK_HOME /opt/android-ndk
ENV ANDROID_NDK_VERSION r22b

RUN apt-get update -qq && \
    apt-get clean && \
    apt install -yy git wget unzip python

# download android-ndk
RUN mkdir /opt/android-ndk-tmp && \
    cd /opt/android-ndk-tmp && \
    wget -nv --show-progress --progress=bar:force:noscroll https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip && \
# uncompress
    unzip -q android-ndk-${ANDROID_NDK_VERSION}-linux-x86_64.zip && \
# move to its final location
    mv ./android-ndk-${ANDROID_NDK_VERSION} ${ANDROID_NDK_HOME} && \
# remove temp dir
    cd ${ANDROID_NDK_HOME} && \
    rm -rf /opt/android-ndk-tmp

RUN \
# check out libsodium
    cd /opt && git clone --branch stable https://github.com/jedisct1/libsodium.git && \
# build libsodium
    cd /opt/libsodium && ./dist-build/android-x86.sh

# run test
RUN cd /opt/libsodium && \
    $ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android19-clang -fPIC -shared -o libtest.o -I test/default -I test/quirks -I libsodium-android-i686/include test/default/hash.c libsodium-android-i686/lib/libsodium.a
jedisct1 commented 3 years ago

You know that platform way better than I do. Can you submit a fix?

Thanks for your help!

jedisct1 commented 3 years ago
$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/i686-linux-android19-clang \
-I test/quirks -I test/default \
-I libsodium-android-i686/include -L libsodium-android-i686/lib \
test/default/hash.c -lsodium

Works for me as well... NDK is r23b2.

ghazel commented 3 years ago

Not surprising that the shared library would work.

jedisct1 commented 3 years ago

For a static build, just add -static to the command-line. Works fine as well.

jedisct1 commented 3 years ago

-fPIC -shared -> build a shared object lib/<some library>.a -> force the linker to use a static library

The message you got from the linker really means "you told me to use a shared library, but didn't give me a shared library". The recompile with -fPIC advice is not about your own files, but about the library you want to link. Granted, that linker message is confusing. Maybe more recent linkers do better.

ghazel commented 3 years ago

The goal is to build a shared object (libtest.so), linking against the static library (libsodium.a). (yes, hash.c is not designed to be a shared object, but it works to reproduce the error). The inclusion of -fPIC in the test is not necessary, but it was to point out that adding it does not fix the issue.