The patch below fixes a build error when building libunistring without --disable-shared on Android 4.3:
FAIL: test-nfc ============== CANNOT LINK EXECUTABLE: /data/data/com.spartacusrex.spartacuside/files/libunistring-0.9.10a/build/tests/.libs/test-nfc invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libunistring.so (built with -Bsymbolic?) FAIL test-nfc (exit status: 1) Some background about this error "invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library": It indicates a reference to a variable (not function) in a shared library. It is a runtime error, emitted by the dynamic linker of Android [1], I saw it in two cases: 1) For a reference to 'stdin', 'stdout', 'stderr': Compiling the following program -------------------- hello.c -------------------- #include <stdio.h> int main () { fprintf(stdout, "Hello world\n"); return 0; } ------------------------------------------------- without -mandroid and without -fPIC and then running the program produces this error. In this case, the following relocations against __sF (an array that contains stdin, stdout, stderr) remain: $ arm-eabi-readelf -r hello.o Relocation section '.rel.text' at offset 0x3f0 contains 3 entries: Offset Info Type Sym.Value Sym. Name 00000020 00000d02 R_ARM_ABS32 00000000 __sF ... $ arm-eabi-readelf -r hello Relocation section '.rel.dyn' at offset 0x2cc contains 1 entries: Offset Info Type Sym.Value Sym. Name 0000947c 00000714 R_ARM_COPY 0000947c __sF $ ./hello CANNOT LINK EXECUTABLE: ./hello invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libc.so (built with -Bsymbolic?) With -mandroid or -fPIC (implied by -mandroid), on the other hand, the program executes fine: $ arm-eabi-readelf -r hello.o Relocation section '.rel.text' at offset 0x444 contains 4 entries: Offset Info Type Sym.Value Sym. Name 00000034 00000e19 R_ARM_BASE_PREL 00000000 _GLOBAL_OFFSET_TABLE_ 00000038 00000f1a R_ARM_GOT_BREL 00000000 __sF 0000003c 00000818 R_ARM_GOTOFF32 00000000 .LC0 ... $ arm-eabi-readelf -r hello Relocation section '.rel.dyn' at offset 0x2cc contains 1 entries: Offset Info Type Sym.Value Sym. Name 00009494 00000715 R_ARM_GLOB_DAT 00000000 __sF $ ./hello Hello world So, a relocation of type R_ARM_ABS32 in the '.text' segment is handled by the binutils, by passing '-mandroid' or '-fPIC'. Namely, the relocation is converted to something the Android dynamic linker can handle. 2) The test program tests/uninorm/test-nfc.c contains a reference to a variable, in an initializer of a variable: uninorm_t n = UNINORM_NFC; where uninorm.h contains: extern const struct unicode_normalization_form uninorm_nfc; #define UNINORM_NFC (&uninorm_nfc) Here, compiling with -mandroid or -fPIC makes no difference. In both cases $ arm-eabi-readelf -r test-nfc.o Relocation section '.rel.data' at offset 0x42c contains 1 entries: Offset Info Type Sym.Value Sym. Name 00000000 00000f02 R_ARM_ABS32 00000000 uninorm_nfc $ arm-eabi-readelf -r .libs/test-nfc Relocation section '.rel.dyn' at offset 0x49c contains 3 entries: Offset Info Type Sym.Value Sym. Name 0000c80c 00000315 R_ARM_GLOB_DAT 0000c818 uninorm_nfc 0000c818 00000314 R_ARM_COPY 0000c818 uninorm_nfc $ LD_LIBRARY_PATH=.... .libs/test-nfc CANNOT LINK EXECUTABLE: .libs/test-nfc invalid R_ARM_COPY relocation against DT_SYMBOLIC shared library libunistring.so (built with -Bsymbolic?) So, a relocation of type R_ARM_ABS32 in the '.data' segment cannot be handled, because '-fPIC' does not help and the dynamic linker does not support it. For comparison, here's the situation of the same program on a glibc system: $ readelf -r test-nfc.o Relocation section '.rel.data.rel' at offset 0x73c contains 1 entry: Offset Info Type Sym.Value Sym. Name 00000000 00001802 R_ARM_ABS32 00000000 uninorm_nfc $ readelf -r .libs/test-nfc Relocation section '.rel.dyn' at offset 0x528 contains 14 entries: Offset Info Type Sym.Value Sym. Name 00015070 00001415 R_ARM_GLOB_DAT 00000000 uninorm_nfc 00015080 00001402 R_ARM_ABS32 00000000 uninorm_nfc ... $ LD_LIBRARY_PATH=../lib/.libs .libs/test-nfc <works> So, on glibc systems, R_ARM_ABS32 relocs in the .o file are not transformed to R_ARM_COPY relocs, and glibc's ld.so handles them fine. I'm not an expert in ELF for ARM [2]; I don't know whether there is a linker option that would fix the issue. So, let me disable this code on Android, like on Windows. [1] https://git.sphere.ly/Kevinjoa/bionic/blob/b69645248887ddb88517b07c1617d390fdce9c9f/linker/linker.cpp line 1276 [2] https://static.docs.arm.com/ihi0044/e/IHI0044E_aaelf.pdf 2019-01-28 Bruno Haible <br...@clisp.org> Fix build error when building a shared libunistring on Android. * tests/uninorm/test-nfc.c (n): Don't define on Android. (main): Add 'volatile', to defeat a GCC optimization that would eliminate the reference. * tests/uninorm/test-nfd.c (n): Don't define on Android. (main): Add 'volatile', to defeat a GCC optimization that would eliminate the reference. * tests/uninorm/test-nfkc.c (n): Don't define on Android. (main): Add 'volatile', to defeat a GCC optimization that would eliminate the reference. * tests/uninorm/test-nfkd.c (n): Don't define on Android. (main): Add 'volatile', to defeat a GCC optimization that would eliminate the reference. diff --git a/tests/uninorm/test-nfc.c b/tests/uninorm/test-nfc.c index b5c4a01..1bda462 100644 --- a/tests/uninorm/test-nfc.c +++ b/tests/uninorm/test-nfc.c @@ -20,7 +20,7 @@ #include "uninorm.h" -#if !WOE32DLL +#if !(WOE32DLL || defined __ANDROID__) /* Check that UNINORM_NFC is defined and links. */ uninorm_t n = UNINORM_NFC; #endif @@ -33,7 +33,7 @@ int main () { /* Check that UNINORM_NFC is defined and links. */ - uninorm_t nf = UNINORM_NFC; + volatile uninorm_t nf = UNINORM_NFC; (void) nf; test_u32_nfc (); diff --git a/tests/uninorm/test-nfd.c b/tests/uninorm/test-nfd.c index bcb2d02..e2e8b62 100644 --- a/tests/uninorm/test-nfd.c +++ b/tests/uninorm/test-nfd.c @@ -20,7 +20,7 @@ #include "uninorm.h" -#if !WOE32DLL +#if !(WOE32DLL || defined __ANDROID__) /* Check that UNINORM_NFD is defined and links. */ uninorm_t n = UNINORM_NFD; #endif @@ -33,7 +33,7 @@ int main () { /* Check that UNINORM_NFD is defined and links. */ - uninorm_t nf = UNINORM_NFD; + volatile uninorm_t nf = UNINORM_NFD; (void) nf; test_u32_nfd (); diff --git a/tests/uninorm/test-nfkc.c b/tests/uninorm/test-nfkc.c index 6df038d..7e76fbb 100644 --- a/tests/uninorm/test-nfkc.c +++ b/tests/uninorm/test-nfkc.c @@ -20,7 +20,7 @@ #include "uninorm.h" -#if !WOE32DLL +#if !(WOE32DLL || defined __ANDROID__) /* Check that UNINORM_NFKC is defined and links. */ uninorm_t n = UNINORM_NFKC; #endif @@ -33,7 +33,7 @@ int main () { /* Check that UNINORM_NFKC is defined and links. */ - uninorm_t nf = UNINORM_NFKC; + volatile uninorm_t nf = UNINORM_NFKC; (void) nf; test_u32_nfkc (); diff --git a/tests/uninorm/test-nfkd.c b/tests/uninorm/test-nfkd.c index ad89e2e..501630c 100644 --- a/tests/uninorm/test-nfkd.c +++ b/tests/uninorm/test-nfkd.c @@ -20,7 +20,7 @@ #include "uninorm.h" -#if !WOE32DLL +#if !(WOE32DLL || defined __ANDROID__) /* Check that UNINORM_NFKD is defined and links. */ uninorm_t n = UNINORM_NFKD; #endif @@ -33,7 +33,7 @@ int main () { /* Check that UNINORM_NFKD is defined and links. */ - uninorm_t nf = UNINORM_NFKD; + volatile uninorm_t nf = UNINORM_NFKD; (void) nf; test_u32_nfkd ();