bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
* Fix build error when building a shared libunistring on Android
@ 2019-01-28 21:01 Bruno Haible
  0 siblings, 0 replies; only message in thread
From: Bruno Haible @ 2019-01-28 21:01 UTC (permalink / raw)
  To: bug-gnulib

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  <bruno@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 ();



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2019-01-28 21:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-28 21:01 Fix build error when building a shared libunistring on Android Bruno Haible

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).