[AArch64] Relax long branch veneer insertion for non STT_FUNC symbol
authorJiong Wang <jiong.wang@arm.com>
Wed, 20 Jan 2016 16:57:59 +0000 (16:57 +0000)
committerJiong Wang <jiong.wang@arm.com>
Thu, 21 Jan 2016 09:57:09 +0000 (09:57 +0000)
  As defined at AArch64 ELF Specification (4.6.7 Call and Jump
  relocations), symbol with type of non STT_FUNC but in different input
  section with relocation place should insert long branch veneer also.

  Meanwhile the current long branch veneer infrastructure havn't considered
  the situation where the branch destination is "sym_value + rela->addend".

  This was OK because we only insert veneer for long call destination is
  STT_FUNC symbol for which the addend is always zero. But as we relax the
  support to other situations by this patch, we need to handle addend be
  non-zero value. For example, for static function, relocation against
  "local symbol" are turned into relocation against "section symbol + offset"
  where there is a valid addend.

  bfd/
* elfnn-aarch64.c (aarch64_type_of_stub): Allow insert long branch
veneer for sym_sec != input_sec.
(elfNN_aarch64_size_stub): Support STT_SECTION symbol.
(elfNN_aarch64_final_link_relocate): Take rela addend into account when
calculation destination.

  ld/
* testsuite/ld-aarch64/farcall-section.d: Delete.
* testsuite/ld-aarch64/farcall-section.s: Delete.
* testsuite/ld-aarch64/farcall-b-section.d: New expectation file.
* testsuite/ld-aarch64/farcall-bl-section.d: Likewise.
* testsuite/ld-aarch64/farcall-b-section.s: New testcase.
* testsuite/ld-aarch64/farcall-bl-section.s: Likewise.
* testsuite/ld-aarch64/aarch64-elf.exp: Likewise.

12 files changed:
bfd/ChangeLog
bfd/elfnn-aarch64.c
ld/ChangeLog
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/farcall-b-none-function.d
ld/testsuite/ld-aarch64/farcall-b-section.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/farcall-b-section.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/farcall-bl-none-function.d
ld/testsuite/ld-aarch64/farcall-bl-section.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/farcall-bl-section.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/farcall-section.d [deleted file]
ld/testsuite/ld-aarch64/farcall-section.s [deleted file]

index dcf21ce0208815d2800a60e1d4692942c45c1f90..c4fd0bbffe1386bb09da4d69f1fbd6266e84fb68 100644 (file)
@@ -1,3 +1,11 @@
+2016-01-21  Jiong Wang  <jiong.wang@arm.com>
+
+       * elfnn-aarch64.c (aarch64_type_of_stub): Allow insert long branch
+       veneer for sym_sec != input_sec.
+       (elfNN_aarch64_size_stub): Support STT_SECTION symbol.
+       (elfNN_aarch64_final_link_relocate): Take rela addend into account when
+       calculation destination.
+
 2016-01-21  Alan Modra  <amodra@gmail.com>
 
        * elf-linux-core.h (swap_linux_prpsinfo32_out): New function.
index 70251f1d52fdd1170a1eed0c7fe338d1247aed95..292470df73ed97768880b172cf7e995cbb31dc4f 100644 (file)
@@ -2655,7 +2655,7 @@ aarch64_type_of_stub (struct bfd_link_info *info,
   bfd_boolean via_plt_p;
 
   if (st_type != STT_FUNC
-      && (sym_sec != bfd_abs_section_ptr))
+      && (sym_sec == input_sec))
     return stub_type;
 
   globals = elf_aarch64_hash_table (info);
@@ -4174,7 +4174,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd,
                      goto error_ret_free_internal;
                    }
 
-                 stub_entry->target_value = sym_value;
+                 stub_entry->target_value = sym_value + irela->r_addend;
                  stub_entry->target_section = sym_sec;
                  stub_entry->stub_type = stub_type;
                  stub_entry->h = hash;
@@ -5280,15 +5280,28 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
        /* Check if a stub has to be inserted because the destination
           is too far away.  */
        struct elf_aarch64_stub_hash_entry *stub_entry = NULL;
-       if (! aarch64_valid_branch_p (value, place))
+
+       /* If the branch destination is directed to plt stub, "value" will be
+          the final destination, otherwise we should plus signed_addend, it may
+          contain non-zero value, for example call to local function symbol
+          which are turned into "sec_sym + sec_off", and sec_off is kept in
+          signed_addend.  */
+       if (! aarch64_valid_branch_p (via_plt_p ? value : value + signed_addend,
+                                     place))
          /* The target is out of reach, so redirect the branch to
             the local stub for this function.  */
        stub_entry = elfNN_aarch64_get_stub_entry (input_section, sym_sec, h,
                                                   rel, globals);
        if (stub_entry != NULL)
-         value = (stub_entry->stub_offset
-                  + stub_entry->stub_sec->output_offset
-                  + stub_entry->stub_sec->output_section->vma);
+         {
+           value = (stub_entry->stub_offset
+                    + stub_entry->stub_sec->output_offset
+                    + stub_entry->stub_sec->output_section->vma);
+
+           /* We have redirected the destination to stub entry address,
+              so ignore any addend record in the original rela entry.  */
+           signed_addend = 0;
+         }
       }
       value = _bfd_aarch64_elf_resolve_relocation (bfd_r_type, place, value,
                                                   signed_addend, weak_undef_p);
index fc01ed61618e77ac222a4226dceba74e3d67e4ed..a6494b89c3c2d92220d7a3955bc1f8d8f3f9f1a9 100644 (file)
@@ -1,3 +1,13 @@
+2016-01-20  Jiong Wang  <jiong.wang@arm.com>
+
+       * testsuite/ld-aarch64/farcall-section.d: Delete.
+       * testsuite/ld-aarch64/farcall-section.s: Delete.
+       * testsuite/ld-aarch64/farcall-b-section.d: New expectation file.
+       * testsuite/ld-aarch64/farcall-bl-section.d: Likewise.
+       * testsuite/ld-aarch64/farcall-b-section.s: New testcase.
+       * testsuite/ld-aarch64/farcall-bl-section.s: Likewise.
+       * testsuite/ld-aarch64/aarch64-elf.exp: Likewise.
+
 2016-01-20  Nick Clifton  <nickc@redhat.com>
 
        PR 19457
index c5c9ad0e97ecc30ad01aee4846e7fbf37ead4fa2..939539ec809a51b9371d9c8bf66e2bbe6ddc4093 100644 (file)
@@ -170,7 +170,6 @@ run_dump_test "pcrel_pic_defined_local"
 
 run_dump_test "limit-b"
 run_dump_test "limit-bl"
-run_dump_test "farcall-section"
 run_dump_test "farcall-back"
 run_dump_test "farcall-b-defsym"
 run_dump_test "farcall-bl-defsym"
@@ -181,6 +180,8 @@ run_dump_test "farcall-bl"
 run_dump_test "farcall-b"
 run_dump_test "farcall-b-none-function"
 run_dump_test "farcall-bl-none-function"
+run_dump_test "farcall-b-section"
+run_dump_test "farcall-bl-section"
 
 run_dump_test "tls-relax-all"
 run_dump_test "tls-relax-gd-le"
index 34a6568dfb1cde0667c74aea65219be22f5cfffa..ba2981fb10ec7497c7946adfd0544cb42694ea76 100644 (file)
@@ -2,4 +2,23 @@
 #source: farcall-b-none-function.s
 #as:
 #ld: -Ttext 0x1000 --section-start .foo=0x8001000
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_JUMP26 against symbol `bar'.*
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:      14000003        b       100c <__bar_veneer>
+    1004:      d65f03c0        ret
+    1008:      14000007        b       1024 <__bar_veneer\+0x18>
+
+.* <__bar_veneer>:
+    100c:      90040010        adrp    x16, 8001000 <bar>
+    1010:      91000210        add     x16, x16, #0x0
+    1014:      d61f0200        br      x16
+       ...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:      d65f03c0        ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b-section.d b/ld/testsuite/ld-aarch64/farcall-b-section.d
new file mode 100644 (file)
index 0000000..4745c0f
--- /dev/null
@@ -0,0 +1,34 @@
+#name: aarch64-farcall-b-section
+#source: farcall-b-section.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:      14000008        b       1020 <___veneer>
+    1004:      14000003        b       1010 <___veneer>
+    1008:      d65f03c0        ret
+    100c:      1400000d        b       1040 <___veneer\+0x20>
+
+.* <___veneer>:
+    1010:      90040010        adrp    x16, 8001000 <bar>
+    1014:      91001210        add     x16, x16, #0x4
+    1018:      d61f0200        br      x16
+    101c:      00000000        .inst   0x00000000 ; undefined
+
+.* <___veneer>:
+    1020:      90040010        adrp    x16, 8001000 <bar>
+    1024:      91000210        add     x16, x16, #0x0
+    1028:      d61f0200        br      x16
+       ...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:      d65f03c0        ret
+
+.* <bar2>:
+ 8001004:      d65f03c0        ret
diff --git a/ld/testsuite/ld-aarch64/farcall-b-section.s b/ld/testsuite/ld-aarch64/farcall-b-section.s
new file mode 100644 (file)
index 0000000..1a135ef
--- /dev/null
@@ -0,0 +1,20 @@
+.global _start
+
+# We will place the section .text at 0x1000.
+
+       .text
+
+_start:
+       b bar
+       b bar2
+       ret
+
+# We will place the section .foo at 0x8001000.
+
+       .section .foo, "xa"
+       .type bar, @function
+bar:
+       ret
+       .type bar2, @function
+bar2:
+       ret
index 6ce9ca45b2994c9e3f436c0e4e7726bdc3776c82..b6a4ddae44a40803e91c4e931704cc5505ba2870 100644 (file)
@@ -2,4 +2,23 @@
 #source: farcall-bl-none-function.s
 #as:
 #ld: -Ttext 0x1000 --section-start .foo=0x8001000
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against symbol `bar'.*
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:      94000003        bl      100c <__bar_veneer>
+    1004:      d65f03c0        ret
+    1008:      14000007        b       1024 <__bar_veneer\+0x18>
+
+.* <__bar_veneer>:
+    100c:      90040010        adrp    x16, 8001000 <bar>
+    1010:      91000210        add     x16, x16, #0x0
+    1014:      d61f0200        br      x16
+       ...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:      d65f03c0        ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-section.d b/ld/testsuite/ld-aarch64/farcall-bl-section.d
new file mode 100644 (file)
index 0000000..2bd4f85
--- /dev/null
@@ -0,0 +1,34 @@
+#name: aarch64-farcall-bl-section
+#source: farcall-bl-section.s
+#as:
+#ld: -Ttext 0x1000 --section-start .foo=0x8001000
+#objdump: -dr
+#...
+
+Disassembly of section .text:
+
+.* <_start>:
+    1000:      94000008        bl      1020 <___veneer>
+    1004:      94000003        bl      1010 <___veneer>
+    1008:      d65f03c0        ret
+    100c:      1400000d        b       1040 <___veneer\+0x20>
+
+.* <___veneer>:
+    1010:      90040010        adrp    x16, 8001000 <bar>
+    1014:      91001210        add     x16, x16, #0x4
+    1018:      d61f0200        br      x16
+    101c:      00000000        .inst   0x00000000 ; undefined
+
+.* <___veneer>:
+    1020:      90040010        adrp    x16, 8001000 <bar>
+    1024:      91000210        add     x16, x16, #0x0
+    1028:      d61f0200        br      x16
+       ...
+
+Disassembly of section .foo:
+
+.* <bar>:
+ 8001000:      d65f03c0        ret
+
+.* <bar2>:
+ 8001004:      d65f03c0        ret
diff --git a/ld/testsuite/ld-aarch64/farcall-bl-section.s b/ld/testsuite/ld-aarch64/farcall-bl-section.s
new file mode 100644 (file)
index 0000000..4469d4d
--- /dev/null
@@ -0,0 +1,20 @@
+       .global _start
+
+# We will place the section .text at 0x1000.
+
+       .text
+
+_start:
+       bl bar
+       bl bar2
+       ret
+
+# We will place the section .foo at 0x8001000.
+
+       .section .foo, "xa"
+       .type bar, @function
+bar:
+       ret
+       .type bar2, @function
+bar2:
+       ret
diff --git a/ld/testsuite/ld-aarch64/farcall-section.d b/ld/testsuite/ld-aarch64/farcall-section.d
deleted file mode 100644 (file)
index 85775e1..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#name: Aarch64 farcall to symbol of type STT_SECTION
-#source: farcall-section.s
-#as:
-#ld: -Ttext 0x1000 --section-start .foo=0x8001014
-#error: .*\(.text\+0x0\): relocation truncated to fit: R_AARCH64_CALL26 against `.foo'
diff --git a/ld/testsuite/ld-aarch64/farcall-section.s b/ld/testsuite/ld-aarch64/farcall-section.s
deleted file mode 100644 (file)
index 86a070c..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-# Test to ensure that an Aarch64 call exceeding 128MB generates an error
-# if the destination is of type STT_SECTION (eg non-global symbol)
-
-       .global _start
-
-# We will place the section .text at 0x1000.
-
-       .text
-
-_start:
-       bl bar
-
-# We will place the section .foo at 0x8001020.
-
-       .section .foo, "xa"
-
-bar:
-       ret
-