]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: aarch64: Require 16 bytes for Morello capinit relocation
authorMatthew Malcomson <matthew.malcomson@arm.com>
Thu, 29 Jul 2021 14:08:35 +0000 (15:08 +0100)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Thu, 29 Jul 2021 14:08:35 +0000 (15:08 +0100)
The `capinit` directive does not allocate space for the relevant
relocation, rather it creates a CAPINIT relocation on the 16 bytes
immediately following it.

Our implementation works by ensuring we can grow the existing `frag` (an
internal structure that describes known contiguous bytes) by 8 bytes
and then recording that we have an 8 byte sized CAPINIT relocation.
It should be 16 bytes, since the relocation is on a 16 byte quantity.

One symptom this problem can cause is where the section that a given
CAPINIT relocation is recorded may not have enough space for the entire
capability the CAPINIT relocation requests.

The testcase we add demonstrated this problem before the current change.
Now it errors out.  Unfortunately the error is an internal one with a
error message that references internal data structures, but I believe
that is better than creating a faulty binary without complaint.

gas/config/tc-aarch64.c
gas/testsuite/gas/aarch64/morello-capinit-require-size.d [new file with mode: 0644]
gas/testsuite/gas/aarch64/morello-capinit-require-size.l [new file with mode: 0644]
gas/testsuite/gas/aarch64/morello-capinit-require-size.s [new file with mode: 0644]

index 77caba2f13996e541b1e5c216a980aa1b91e038e..89abdc62e4e97049856d6d22966b90ae147a52bf 100644 (file)
@@ -2170,8 +2170,8 @@ s_aarch64_capinit (int ignored ATTRIBUTE_UNUSED)
       return;
     }
 
-  frag_grow (8);
-  fix_new_aarch64 (frag_now, frag_more (0) - frag_now->fr_literal, 8, &exp, 0,
+  frag_grow (16);
+  fix_new_aarch64 (frag_now, frag_more (0) - frag_now->fr_literal, 16, &exp, 0,
                   BFD_RELOC_MORELLO_CAPINIT);
 
   demand_empty_rest_of_line ();
diff --git a/gas/testsuite/gas/aarch64/morello-capinit-require-size.d b/gas/testsuite/gas/aarch64/morello-capinit-require-size.d
new file mode 100644 (file)
index 0000000..8a6370e
--- /dev/null
@@ -0,0 +1,3 @@
+#name: Capinit Requires 16 bytes
+#as: -march=armv8-a+c64
+#error_output: morello-capinit-require-size.l
diff --git a/gas/testsuite/gas/aarch64/morello-capinit-require-size.l b/gas/testsuite/gas/aarch64/morello-capinit-require-size.l
new file mode 100644 (file)
index 0000000..614213d
--- /dev/null
@@ -0,0 +1,2 @@
+[^:]*: Assembler messages:
+[^:]*:7: Error: internal error: fixup not contained within frag
diff --git a/gas/testsuite/gas/aarch64/morello-capinit-require-size.s b/gas/testsuite/gas/aarch64/morello-capinit-require-size.s
new file mode 100644 (file)
index 0000000..6931c49
--- /dev/null
@@ -0,0 +1,17 @@
+.data
+.align 4
+a:
+       .8byte 0
+
+d:
+       .capinit a
+       .8byte 0
+       .size d, .-d
+
+// Need to switch section so that the capinit relocation does not have enough
+// space in the relevant chunk.
+.section .data.rel.ro
+.align 4
+e:
+       .8byte 0
+       .size e, .-e