This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][AArch64] Improve copy relocation support on four absolute relocation types


aarch64 static linker fail linking unreasonably when trying to link executable from .o
written by handle assembly which contain access of global symbol and generated without -fPIC.

/usr/bin/ld: x.o(.text+0x8): unresolvable R_AARCH64_MOVW_UABS_G0_NC relocation against...
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status

I found the problem is caused by our incomplete support for calculating address of
global symbol by absolute relocation.

currently, if we calculating address by 32/64 bit absolute relocation, it's OK.

for example:

x.s
.8byte global_a for .o, a ABS64 relocation created.

Relocation section '*.rela.text*' at offset 0x360 contains 1 entries:

R_AARCH64_ABS64        0000000000000000 global_a + 0
then if we:

  link into executable
  ============================
  copy relocation generated, and the original address in text section
  will point to .dynbss which this copy relocation will happen.

  *readelf -r x.exe*

  Relocation section '*.rela.dyn*' at offset 0x460 contains 9 entries:

    R_AARCH64_COPY         0000000000410830 stdout + 0

  link into shared library
  ========================
  R_AARCH64_ABS64 will be propagated to dynamic relocation section to let the
  runtime linker relocate on the text section directly.

  *readelf -r x.so*

  Relocation section '*.rela.dyn*' at offset 0x460 contains 9 entries:

    R_AARCH64_ABS64        0000000000000000 stdout + 0
while there is another way to form 64 bit address for global symbol by using movz x0,:abs_g0_nc:global_a (BFD_RELOC_AARCH64_MOVW_G0_NC)
  movk x0,:abs_g1_nc:global_a (BFD_RELOC_AARCH64_MOVW_G1_NC)
  movk x0,:abs_g2_nc:global_a (BFD_RELOC_AARCH64_MOVW_G2_NC)
  movk x0,:abs_g3:global_a    (BFD_RELOC_AARCH64_MOVW_G3)

to form the address from pieces instead of one single R_AARCH64_ABS64.

so for the above four relocation types, we need to support all those logic
AARCH64_ABS64 supported except when linking shared library to prevent
copy on write penalty.

 * for executable linking, generate copy relocation.
 * reject them when linking shared library.

this is also the approach arm32 adopted.

ok for trunk?

thanks.

-- Jiong

  bfd/
    * elfnn-aarch64.c (elfNN_aarch64_check_relocs): Initialize non_got_ref
    properly for MOVW_G0/1/2_NC and MOVW_G3. Reject them when linking
    shared library.
    (elfNN_aarch64_gc_sweep_hook): Add check on these relocs.

  ld/testsuite/
    * ld-aarch64/copy-relocs-so.s: New test file.
    * ld-aarch64/copy-relocs-exe.s: Likewise.
    * ld-aarch64/copy-relocs.d: New expectation file.
    * ld-aarch64/emit-relocs-264-bad.d: New test file.
    * ld-aarch64/emit-relocs-266-bad.d: Likewise.
    * ld-aarch64/emit-relocs-268-bad.d: Likewise.
    * ld-aarch64/emit-relocs-269-bad.d: Likewise.
    * ld-aarch64/aarch64-elf.exp: Run new added test.
commit 755d9ef68978198eb3e022d6fad86e4a54f97f2b
Author: Jiong Wang <jiong.wang@arm.com>
Date:   Mon Aug 11 14:52:24 2014 +0100

    Fix

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 4dfb604..d7b3037 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -4766,16 +4766,6 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
 	    }
 	  break;
 
-	case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
-	case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
-	case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
-	  if (h != NULL && info->executable)
-	    {
-	      if (h->plt.refcount > 0)
-		h->plt.refcount -= 1;
-	    }
-	  break;
-
 	case BFD_RELOC_AARCH64_CALL26:
 	case BFD_RELOC_AARCH64_JUMP26:
 	  /* If this is a local symbol then we resolve it
@@ -4787,6 +4777,13 @@ elfNN_aarch64_gc_sweep_hook (bfd *abfd,
 	    h->plt.refcount -= 1;
 	  break;
 
+	case BFD_RELOC_AARCH64_MOVW_G0_NC:
+	case BFD_RELOC_AARCH64_MOVW_G1_NC:
+	case BFD_RELOC_AARCH64_MOVW_G2_NC:
+	case BFD_RELOC_AARCH64_MOVW_G3:
+	case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
+	case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
+	case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
 	case BFD_RELOC_AARCH64_NN:
 	  if (h != NULL && info->executable)
 	    {
@@ -5283,6 +5280,22 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 	    break;
 	  }
 
+	case BFD_RELOC_AARCH64_MOVW_G0_NC:
+	case BFD_RELOC_AARCH64_MOVW_G1_NC:
+	case BFD_RELOC_AARCH64_MOVW_G2_NC:
+	case BFD_RELOC_AARCH64_MOVW_G3:
+	  if (info->shared)
+	    {
+	      int howto_index = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START;
+	      (*_bfd_error_handler)
+		(_("%B: relocation %s against `%s' can not be used when making "
+		   "a shared object; recompile with -fPIC"),
+		 abfd, elfNN_aarch64_howto_table[howto_index].name,
+		 (h) ? h->root.root.string : "a local symbol");
+	      bfd_set_error (bfd_error_bad_value);
+	      return FALSE;
+	    }
+
 	case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
 	case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
 	case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp
index 36babf3..b3f6eb5 100644
--- a/ld/testsuite/ld-aarch64/aarch64-elf.exp
+++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp
@@ -51,11 +51,15 @@ run_dump_test "emit-relocs-260-be"
 run_dump_test "emit-relocs-262"
 run_dump_test "emit-relocs-263"
 run_dump_test "emit-relocs-264"
+run_dump_test "emit-relocs-264-bad"
 run_dump_test "emit-relocs-265"
 run_dump_test "emit-relocs-266"
+run_dump_test "emit-relocs-266-bad"
 run_dump_test "emit-relocs-267"
 run_dump_test "emit-relocs-268"
+run_dump_test "emit-relocs-268-bad"
 run_dump_test "emit-relocs-269"
+run_dump_test "emit-relocs-269-bad"
 run_dump_test "emit-relocs-270"
 run_dump_test "emit-relocs-270-bad"
 run_dump_test "emit-relocs-271"
@@ -163,3 +167,12 @@ run_dump_test "ifunc-21"
 run_dump_test "ifunc-22"
 
 run_dump_test "relasz"
+
+set aarch64elflinktests {
+  {"ld-aarch64/so with global symbol" "-shared" "" "" {copy-reloc-so.s}
+  {} "copy-reloc-so.so"}
+  {"ld-aarch64/exe with copy relocation" "-e0 tmpdir/copy-reloc-so.so" "" ""
+  {copy-reloc-exe.s} {{objdump -R copy-reloc.d}} "copy-reloc"}
+}
+
+run_ld_link_tests $aarch64elflinktests
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-exe.s b/ld/testsuite/ld-aarch64/copy-reloc-exe.s
new file mode 100644
index 0000000..cafc700
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/copy-reloc-exe.s
@@ -0,0 +1,7 @@
+	.text
+	.global main
+main:
+	movz x0,:abs_g0_nc:global_a
+	movk x0,:abs_g1_nc:global_a
+	movk x0,:abs_g2_nc:global_a
+	movk x0,:abs_g3:global_a
diff --git a/ld/testsuite/ld-aarch64/copy-reloc-so.s b/ld/testsuite/ld-aarch64/copy-reloc-so.s
new file mode 100644
index 0000000..07ec44a
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/copy-reloc-so.s
@@ -0,0 +1,6 @@
+	.global global_a
+	.type	global_a, %object
+	.size	global_a, 4
+	.data
+global_a:
+	.word 0xcafedead
diff --git a/ld/testsuite/ld-aarch64/copy-reloc.d b/ld/testsuite/ld-aarch64/copy-reloc.d
new file mode 100644
index 0000000..c4eed84
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/copy-reloc.d
@@ -0,0 +1,4 @@
+.*
+DYNAMIC RELOCATION RECORDS
+OFFSET.*TYPE.*VALUE.*
+.*R_AARCH64_COPY.*global_a
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-264-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-264-bad.d
new file mode 100644
index 0000000..22718ca
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-264-bad.d
@@ -0,0 +1,3 @@
+#source: emit-relocs-264.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 -shared
+#error: .*relocation R_AARCH64_MOVW_UABS_G0_NC.*can not.*shared object.*fPIC
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-266-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-266-bad.d
new file mode 100644
index 0000000..886494d
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-266-bad.d
@@ -0,0 +1,3 @@
+#source: emit-relocs-266.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 -shared
+#error: .*relocation R_AARCH64_MOVW_UABS_G1_NC.*can not.*shared object.*fPIC
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-268-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-268-bad.d
new file mode 100644
index 0000000..ea97541
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-268-bad.d
@@ -0,0 +1,3 @@
+#source: emit-relocs-268.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 -shared
+#error: .*relocation R_AARCH64_MOVW_UABS_G2_NC.*can not.*shared object.*fPIC
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-269-bad.d b/ld/testsuite/ld-aarch64/emit-relocs-269-bad.d
new file mode 100644
index 0000000..9292855
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/emit-relocs-269-bad.d
@@ -0,0 +1,3 @@
+#source: emit-relocs-269.s
+#ld: -T relocs.ld --defsym tempy=0x11000 --defsym tempy2=0x45000 --defsym tempy3=0x1234  -e0 -shared
+#error: .*relocation R_AARCH64_MOVW_UABS_G3.*can not.*shared object.*fPIC

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]