The expected disassembly for this test is testing for the wrong thing: it
expects the adrp immediate to be zero-extended instead of sign-extended, which
is incorrect. That shows up as a test failure after fixing the disassembly in
the previous patch. This patch fixes the test.
Tested on aarch64-none-elf, OK for users/ARM/morello-binutils-gdb-master?
Thanks,
Alex
Hi,
I'm submitting this patch on behalf of Benjamin Teoh <benjamin.teoh(a)arm.com>.
Regression testing on aarch64-none-elf showed the patch needed the expected
disassembly for an existing test changing, I'll submit that as a follow-on fix
in 2/2.
OK for users/ARM/morello-binutils-gdb-master?
Thanks,
Alex
-- >8 --
When an adrp instruction references a symbol that is more than a page
in memory behind the instruction, it would have a negative offset.
An example of this is:
foo:
nop
.zero 4096
adrp c0, foo
where adrp references 'foo' that is more than a page in memory behind
it.
In the case where the offset is negative, when translating from its
binary format, the offset was seen as an unsigned integer, which
caused a spurious high bit set in the resolved address in the adrp
instruction like in:
0000000000400078 <foo>:
400078: d503201f nop
...
40107c: f0ffffe0 adrp c0, 100400000 <__bss_end__+0xfffeeff8>
There was an issue with how the imm field of the adrp instruction was
extracted in `aarch64_ext_imm`. The value was not sign extended
correctly for capability mode targets. This was caused by the imm
field having its `P` bit being removed before the sign extension,
which is exclusive to 64-bit capability targets. This was remedied
by shortening the width of the imm field before sign extending the
imm value, resulting in:
0000000000400078 <foo>:
400078: d503201f nop
...
40107c: f0ffffe0 adrp c0, 400000 <foo-0x78>
Hi,
While the concept of a core instruction relates to the idea of
instructions that are available irrespective of the presence of
architectural extensions, this concept breaks down with the
introduction of the Morello architecture.
Rather, what is observed in Morello is that when PSTATE.C64 == 1,
the A64C_INSN variant becomes the ONLY valid aarch64_opcode variant,
with the CORE_INSN variant becoming illegal. Therefore, some way of
ruling out the use of such CORE_INSNs is needed.
Similarly, some A64C_INSN instructions are only valid for
PSTATE.C64 == 1 and are not valid when compiling for Morello A64
mode.
At the assembly level, the CORE_INSN and A64C_INSN variants share the
same mnemonic, differing only by whether they are passed a general-
purpose register argument or its capability counterpart, e.g.
* CORE_INSN: adr x0, #0
* A64C_INSN: adr c0, #0
This makes the prospect of combining both insn variants in binutils
into a single insn entry in aarch64_opcode_table[], resolving the
appropriate operand code (e.g. AARCH64_OPND_Can versus
AARCH64_OPND_Rn) at compile time by analyzing the -march and -mabi
flags.
This approach falls short when dealing with instructions such as `bl'
where the core and morello instructions share the same mnemonic but
have distinct encodings.
A more flexible approach is therefore presented here. Special
restrictions to instructions are encoded in the FLAGS field, which
can then be used in checks carried out in `md_assemble'.
This fixes two issues:
1. Wrong fix suggestions in `output_operand_error_record':
- attempting to assemble `adr w0, #0' at present, for example,
results in a suggestion that `w0' be changed to `x0' as opposed
to `c0'.
2. Purecap only instructions being accepted when assembling without
the C64 extension:
- `adr c0, #0' is currently accepted when assembling for
Hybrid mode.
This patch defines the F_NONC64 and F_C64ONLY flags for labellig these
instructions in aarch64_opcode.flags, such that unavailable instructions
could be identified by cross-referencing this field along with whether
C64 is set in the `cpu_variant' aarch64_feature_set variable. When
the conditions set by the flag is not met by `cpu_variant', the
instruction can be attributed a AARCH64_OPDE_SYNTAX_ERROR, allowing
for correct error handling in md_assemble.
OK for morello branch?
Thanks,
Victor
ChangeLog:
* include/opcode/aarch64.h (F_NONC64): New flag.
* include/opcode/aarch64.h (F_C64ONLY): Likewise.
opcodes/ChangeLog:
* aarch64-tbl.h (aarch64_opcode_table): Add F_NONC64 and F_C64ONLY
to relevant aarch64_opcodes
gas/ChangeLog:
* config/tc-aarch64.c (validate_opcode_for_feature): New.
(md_assemble): Use `validate_opcode_for_feature' in template
selection.
* gas/testsuite/gas/aarch64/morello-exclude.l: New testcase.
* gas/testsuite/gas/aarch64/morello-exclude.s: Likewise.
* gas/testsuite/gas/aarch64/morello-exclude.l: Likewise.
* gas/testsuite/gas/aarch64/morello_insn.s: Fix hybrid codegen.
---
gas/config/tc-aarch64.c | 33 ++++++++++++++++++++-
gas/testsuite/gas/aarch64/morello-exclude.d | 4 +++
gas/testsuite/gas/aarch64/morello-exclude.l | 9 ++++++
gas/testsuite/gas/aarch64/morello-exclude.s | 8 +++++
gas/testsuite/gas/aarch64/morello_insn.s | 7 ++++-
include/opcode/aarch64.h | 8 ++++-
opcodes/aarch64-tbl.h | 12 ++++----
7 files changed, 72 insertions(+), 9 deletions(-)
create mode 100644 gas/testsuite/gas/aarch64/morello-exclude.d
create mode 100644 gas/testsuite/gas/aarch64/morello-exclude.l
create mode 100644 gas/testsuite/gas/aarch64/morello-exclude.s
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index c8373b311dd..66c93248c2a 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -7642,6 +7642,36 @@ dump_opcode_operands (const aarch64_opcode *opcode)
}
#endif /* DEBUG_AARCH64 */
+/* With the introduction of Morello, some CORE_INSNs are no longer
+ valid if IS_C64 is true. It is important that such instructions
+ are no longer treated as core in such contexts and are
+ disconsidered, rather being treated as belonging to any other
+ unavailable architectural extension. Likewise, reject purecap-specific
+ instructions when assembling for hybrid (or any other) tartgets. */
+
+static bfd_boolean
+validate_opcode_for_feature (const aarch64_opcode *opcode,
+ aarch64_feature_set features)
+{
+ /* If opcode is memory-related, Ensure this CPU does not impose any
+ restriction on allowed operands. */
+ if (opcode->flags & F_NONC64
+ && AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_C64))
+ {
+ set_default_error ();
+ return FALSE;
+ }
+ /* Reject purecap-specific instructions when assembling for any other
+ target. */
+ if (opcode->flags & F_C64ONLY
+ && !(AARCH64_CPU_HAS_FEATURE (features, AARCH64_FEATURE_C64)))
+ {
+ set_default_error ();
+ return FALSE;
+ }
+ return TRUE;
+}
+
/* This is the guts of the machine-dependent assembler. STR points to a
machine dependent instruction. This function is supposed to emit
the frags/bytes it assembles to. */
@@ -7736,7 +7766,8 @@ md_assemble (char *str)
continue;
}
- if (parse_operands (p, opcode)
+ if (validate_opcode_for_feature (opcode, cpu_variant)
+ && parse_operands (p, opcode)
&& programmer_friendly_fixup (&inst)
&& do_encode (inst_base->opcode, &inst.base, &inst_base->value))
{
diff --git a/gas/testsuite/gas/aarch64/morello-exclude.d
b/gas/testsuite/gas/aarch64/morello-exclude.d
new file mode 100644
index 00000000000..df137cc01d2
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/morello-exclude.d
@@ -0,0 +1,4 @@
+#name: Morello opcode filter
+#as: -march=morello+c64 -mabi=purecap
+#source: morello-exclude.s
+#error_output: morello-exclude.l
\ No newline at end of file
diff --git a/gas/testsuite/gas/aarch64/morello-exclude.l
b/gas/testsuite/gas/aarch64/morello-exclude.l
new file mode 100644
index 00000000000..5502e9c89d7
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/morello-exclude.l
@@ -0,0 +1,9 @@
+[^:]+: Assembler messages:
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adr w0,#0'
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adr x0,#0'
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adrp
w0,#0'
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `adrp
x0,#0'
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `blr w0'
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `blr x0'
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `ret w0'
+[^:]+:[0-9]+: Error: operand 1 must be a Capability register -- `ret x0'
diff --git a/gas/testsuite/gas/aarch64/morello-exclude.s
b/gas/testsuite/gas/aarch64/morello-exclude.s
new file mode 100644
index 00000000000..b920ba340c1
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/morello-exclude.s
@@ -0,0 +1,8 @@
+ adr w0, #0
+ adr x0, #0
+ adrp w0, #0
+ adrp x0, #0
+ blr w0
+ blr x0
+ ret w0
+ ret x0
diff --git a/gas/testsuite/gas/aarch64/morello_insn.s
b/gas/testsuite/gas/aarch64/morello_insn.s
index e9fc24d22fd..4a9f9b0ff02 100644
--- a/gas/testsuite/gas/aarch64/morello_insn.s
+++ b/gas/testsuite/gas/aarch64/morello_insn.s
@@ -72,7 +72,12 @@ Label:
\op \cd, Label
.endr
.endm
-morello_adrx c0
+
+ .ifdef C64MODE
+ morello_adrx c0
+ .else
+ morello_adrx x0
+ .endif
.ifdef C64MODE
adrdp c0, #4096
diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h
index 9c8127bb157..6297d3138fa 100644
--- a/include/opcode/aarch64.h
+++ b/include/opcode/aarch64.h
@@ -969,7 +969,13 @@ extern aarch64_opcode aarch64_opcode_table[];
#define F_SCAN (1ULL << 31)
/* Do no shift immediate operand. */
#define F_NOSHIFT (1ULL << 32)
-/* Next bit is 33. */
+/* Opcode variant is invalidated by PSTATE.C64. When PSTATE.C64 == 1,
operation
+ requires use of capability operands. */
+#define F_NONC64 (1ULL << 33)
+/* Opcode vatiant not suitable for morello hybrid mode and will fail unless
+ PSTATE.C64 == 1. */
+#define F_C64ONLY (1ULL << 34)
+/* Next bit is 35. */
/* Instruction constraints. */
/* This instruction has a predication constraint on the instruction at
PC+4. */
diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h
index a8f7fe047cd..bda6ea58936 100644
--- a/opcodes/aarch64-tbl.h
+++ b/opcodes/aarch64-tbl.h
@@ -3395,9 +3395,9 @@ struct aarch64_opcode aarch64_opcode_table[] =
CORE_INSN ("b", 0x14000000, 0xfc000000, branch_imm, OP_B, OP1
(ADDR_PCREL26), QL_PCREL_26, 0),
CORE_INSN ("bl", 0x94000000, 0xfc000000, branch_imm, OP_BL, OP1
(ADDR_PCREL26), QL_PCREL_26, 0),
/* Unconditional branch (register). */
- CORE_INSN ("br", 0xd61f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn),
QL_I1X, 0),
- CORE_INSN ("blr", 0xd63f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn),
QL_I1X, 0),
- CORE_INSN ("ret", 0xd65f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn),
QL_I1X, F_OPD0_OPT | F_DEFAULT (30)),
+ CORE_INSN ("br", 0xd61f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn),
QL_I1X, F_NONC64),
+ CORE_INSN ("blr", 0xd63f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn),
QL_I1X, F_NONC64),
+ CORE_INSN ("ret", 0xd65f0000, 0xfffffc1f, branch_reg, 0, OP1 (Rn),
QL_I1X, F_OPD0_OPT | F_DEFAULT (30) | F_NONC64),
CORE_INSN ("eret", 0xd69f03e0, 0xffffffff, branch_reg, 0, OP0 (),
{}, 0),
CORE_INSN ("drps", 0xd6bf03e0, 0xffffffff, branch_reg, 0, OP0 (),
{}, 0),
V8_3_INSN ("braa", 0xd71f0800, 0xfffffc00, branch_reg, OP2 (Rn,
Rd_SP), QL_I2SAMEX, 0),
@@ -3986,10 +3986,10 @@ struct aarch64_opcode aarch64_opcode_table[] =
CORE_INSN ("mov", 0x52800000, 0x7f800000, movewide,
OP_MOV_IMM_WIDE, OP2 (Rd, IMM_MOV), QL_DST_R, F_SF | F_ALIAS | F_CONV),
CORE_INSN ("movk", 0x72800000, 0x7f800000, movewide, OP_MOVK, OP2
(Rd, HALF), QL_DST_R, F_SF),
/* PC-rel. addressing. */
- CORE_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Rd,
ADDR_PCREL21), QL_ADRP, 0),
- CORE_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Rd,
ADDR_ADRP), QL_ADRP, 0),
+ CORE_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Rd,
ADDR_PCREL21), QL_ADRP,F_NONC64),
+ CORE_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Rd,
ADDR_ADRP), QL_ADRP, F_NONC64),
/* Pc-rel. addressing with capabilities. */
- A64C_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Cad,
ADDR_PCREL21), QL2_A64C_CA_NIL, 0),
+ A64C_INSN ("adr", 0x10000000, 0x9f000000, pcreladdr, 0, OP2 (Cad,
ADDR_PCREL21), QL2_A64C_CA_NIL, F_C64ONLY),
A64C_INSN ("adrp", 0x90000000, 0x9f000000, pcreladdr, 0, OP2 (Cad,
ADDR_ADRP), QL2_A64C_CA_NIL, 0),
A64C_INSN ("adrdp", 0x90000000, 0x9f800000, pcreladdr, 0, OP2 (Cad,
A64C_ADDR_ADRDP), QL2_A64C_CA_NIL, 0),
/* A64C Instructions. */
--
2.17.1
Hi!
I am looking for instructions on how to run a bare metal binary generated by GCC under FVP.
For example:
#include <stdio.h>
int main()
{
fprintf(stderr,"hello world!\n");
}
Currently, I compile it with:
aarch64-none-elf-gcc -march=morello+c64 -mabi=purecap -specs=rdimon.specs -std=c11 -gdwarf-4 -pedantic dummy.c
Ideally, I would like to run it without UI and capture the output for test automation.
I tried, naively, the following (suggested by a colleague):
$ ~/cheri/output/morello-sdk/FVP_Morello/models/Linux64_GCC-6.4/FVP_Morello -q -C disable_visualisation=true -C css.terminal_uart_ap.quiet=1 -C board.terminal_uart0_board.start_telnet=0 -C board.terminal_uart0_board.quiet=1 -C board.terminal_uart1_board.start_telnet=0 -C board.terminal_uart1_board.quiet=1 -C css.mcp.terminal_uart0.start_telnet=0 -C css.mcp.terminal_uart0.quiet=1 -C css.mcp.terminal_uart1.start_telnet=0 -C css.mcp.terminal_uart1.quiet=1 -C css.scp.terminal_uart_aon.start_telnet=0 -C css.scp.terminal_uart_aon.quiet=1 -C css.terminal_sec_uart_ap.start_telnet=0 -C css.terminal_sec_uart_ap.quiet=1 -C css.terminal_uart1_ap.start_telnet=0 -C css.terminal_uart1_ap.quiet=1 --cyclelimit 2000000 --start 0x00000010310000 -a a.out
but it did not work.
Vadim
--
Senior Research Associate
Department of Computer Science and Technology
University of Cambridge
http://zaliva.org/
I am very excited about the binary release of gcc-toolchain, but I run into problems trying to compile something as simple as:
int main()
{
return 0;
}
$ ~/morello-gnu/bin/aarch64-none-elf-gcc -march=morello -O0 -nostdlib hello.c
/home/lord/morello-gnu/bin/../lib/gcc/aarch64-none-elf/10.1.0/../../../../aarch64-none-elf/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000400000
$ ~/morello-gnu/bin/aarch64-none-elf-gcc -march=morello -O0 hello.c
/home/lord/morello-gnu/bin/../lib/gcc/aarch64-none-elf/10.1.0/../../../../aarch64-none-elf/bin/ld: /home/lord/morello-gnu/bin/../lib/gcc/aarch64-none-elf/10.1.0/../../../../aarch64-none-elf/lib/hybridcap/libc.a(lib_a-exit.o): in function `exit':
/data/jenkins/workspace/GNU-toolchain/morello-trunk/src/newlib-cygwin/newlib/libc/stdlib/exit.c:70: undefined reference to `_exit'
/home/lord/morello-gnu/bin/../lib/gcc/aarch64-none-elf/10.1.0/../../../../aarch64-none-elf/bin/ld: /home/lord/morello-gnu/bin/../lib/gcc/aarch64-none-elf/10.1.0/../../../../aarch64-none-elf/lib/hybridcap/crt0.o: in function `_start':
/data/jenkins/workspace/GNU-toolchain/morello-trunk/src/newlib-cygwin/libgloss/aarch64/crt0.S:360: undefined reference to `__init_global_caps'
/home/lord/morello-gnu/bin/../lib/gcc/aarch64-none-elf/10.1.0/../../../../aarch64-none-elf/bin/ld: /data/jenkins/workspace/GNU-toolchain/morello-trunk/src/newlib-cygwin/libgloss/aarch64/crt0.S:361: undefined reference to `__processRelocs'
/home/lord/morello-gnu/bin/../lib/gcc/aarch64-none-elf/10.1.0/../../../../aarch64-none-elf/bin/ld: /data/jenkins/workspace/GNU-toolchain/morello-trunk/src/newlib-cygwin/libgloss/aarch64/crt0.S:365: undefined reference to `initialise_monitor_handles'
collect2: error: ld returned 1 exit status
Any suggestions on what I am doing wrong?
Also, I think it mentions that pure and hybrid capabilities modes are supported, but I could not find option to specify which one to use.
Thanks!
Vadim
--
Senior Research Associate
Department of Computer Science and Technology
University of Cambridge
http://zaliva.org/
The symbol that objdump reports for the start of the data section is not
important and is different between linux and bare metal builds.
Just avoiding specifying this symbol in our testcase fixes a testsuite
failure in the linux build.
############### Attachment also inlined for ease of reply ###############
diff --git a/ld/testsuite/ld-aarch64/morello-large-function.d b/ld/testsuite/ld-aarch64/morello-large-function.d
index dc0af92e12f9ab7203a400997ded14c8bdf4172c..55f87d3a4db8d0af011bd5c10ebca289d679e868 100644
--- a/ld/testsuite/ld-aarch64/morello-large-function.d
+++ b/ld/testsuite/ld-aarch64/morello-large-function.d
@@ -15,7 +15,7 @@
Disassembly of section \.data:
-[0-9a-f]+ <__data_start>:
+[0-9a-f]+ <.*>:
*[0-9a-f]+: .*
.*: R_MORELLO_RELATIVE \*ABS\*\+.*
*[0-9a-f]+: .* udf #0
GNU bfd linker removes duplicate CIE and FDE entries in the exception
handling information. When it does this entries in the .eh_frame
section end up in different positions to where they were originally.
In order to account for that, when the linker removes an FDE/CIE entry
from one object's .eh_frame section in order to prefer an equivalent
entry in another object's .eh_frame section, the linker adjusts symbols
which were pointing to the first entry to point to the second.
If the assembler has changed symbols pointing into the .eh_frame section
such that they are now described by a section symbol plus offset, the
linker can not perform this transformation. This means that symbols can
end up pointing at different information than they originally pointed
at.
NOTE1: This changes the behaviour of this on *all* targets. As it
stands that seems like the correct approach since the linker behaviour
that we are accounting for is a general behaviour. On top of that, this
translation should not make a change in functionality if the linker
behaviour were not enabled for some target (since without the linker
behaviour this transformation should not affect anything -- which is why
it's believed to be safe in the first place). However it is still
important to note that we have not actually tested these changes on
other architectures.
NOTE2: Since the GNU linker makes its decision to look for items to
merge or not based on the *output* section name, there is a mapping
between output sections and input sections that can be modified by the
user, and we may not even be using the GNU linker in the first place,
our patch can not be 100% accurate and robust when choosing which
sections to avoid this adjustment.
It is still desirable to avoid problematic adjustment in the common case
of using the GNU linker with the default mapping between input sections
and output sections. Though it may not be desirable to hard-code a
feature of the default linker script at the time of writing this patch
into GAS.
Here we use the same check that the assembler uses in gas/dw2gencfi.c to
identify a .eh_frame section. This has the benefits of being a check
the assembler is using already (so the assembler is internally
consistent) and matching the split that the default bfd linker scripts
make between all input sections that said scripts name.
E.g. the default linker script for aarch64-none-elf matches the
following patterns for an output section named .eh_frame_hdr
{ *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
and matches the below for an output section named .eh_frame
{ KEEP (*(.eh_frame)) *(.eh_frame.*) }.
The linker then applies the problematic transformation to the .eh_frame
output section and not to the .eh_frame_hdr section.
The check we use here makes a corresponding decision to all sections
which would be caught by the above patterns. I.e. it avoids adjusting
symbols in sections which would end up in the .eh_frame output section
and does not avoid adjusting symbols in sections which would end up in
the .eh_frame_hdr output section.
NOTE3: This behaviour by itself is not causing any problems for us. The
trigger for making this change (especially in morello binutils) is that
when crtbeginT.o "registers" an object's exception handling information
with a static glibc, it uses `adrp` and `add` to access the
__EH_FRAME_BEGIN__ symbol. Currently the relocation on `adrp` is
adjusted into a "section symbol plus offset" transformation (which ends
up as exactly the start of the section symbol in the crtbeginT.o
object), but the `add` instruction is not adjusted in this way.
It is this *difference* that is problematic.
It means that we can end up with a broken pointer using the
.eh_frame page and the __EH_FRAME_BEGIN__ offset into a page.
With base AArch64, both these instructions would be adjusted to point to
the .eh_frame section of crtbeginT.o. This is still a buggy behaviour
in the assembler due to the reasons given above, but it at least meant
that the static glibc got a sensible pointer (though one starting after
any exception frame information on the crti.o and crt1.o object files).
With this change, both instructions stay pointing at __EH_FRAME_BEGIN__
in the object file. That means that the linker will leave both
instructions pointing at the same place after de-duplication of
exception information. That place is not guaranteed to be the start of
the total exception frame information, but in practice it is always
closer to the start of the debug frame than without having made this
patch.
We could have stopped static glibc from crashing by making sure that we
accessed the .eh_frame section symbol for both instructions rather than
using __EH_FRAME_BEGIN__ for both. This would behave in the same way as
stock AArch64.
This would mean that static glibc would not be affected by the
particulars of how the GNU bfd linker merges CIE and FDE entries
together. On the other hand it would mean that static glibc would never
have the ability to unwind through start code in crt1.o and crti.o.
I don't have a particularly strong opinion on which of these is the best
approach, I chose this one since it gives the static glibc access to the
full debug information for the moment.
############### Attachment also inlined for ease of reply ###############
diff --git a/gas/testsuite/gas/aarch64/eh-frame-symbols.d b/gas/testsuite/gas/aarch64/eh-frame-symbols.d
new file mode 100644
index 0000000000000000000000000000000000000000..8276648ea1c5ea1ce7cd945ecfdf952cd71a0911
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/eh-frame-symbols.d
@@ -0,0 +1,24 @@
+# Checking that our relocations against the symbol __EH_FRAME_BEGIN__ are not
+# transformed into relocations against the section symbol .eh_frame.
+#as: -march=morello+c64
+#objdump: -dr
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+.* <get_eh_frame_begin>:
+ *[0-9a-f]+: ........ stp c29, c30, \[csp, #-64\]!
+ *[0-9a-f]+: ........ adrp c0, 0 <get_eh_frame_begin>
+ 4: R_MORELLO_ADR_PREL_PG_HI20 __EH_FRAME_BEGIN__
+ *[0-9a-f]+: ........ adrp c0, 0 <get_eh_frame_begin>
+ 8: R_MORELLO_ADR_PREL_PG_HI20 \.eh_frame
+ *[0-9a-f]+: ........ add c0, c0, #0x0
+ c: R_AARCH64_ADD_ABS_LO12_NC __EH_FRAME_BEGIN__
+ *[0-9a-f]+: ........ add c0, c0, #0x0
+ 10: R_AARCH64_ADD_ABS_LO12_NC \.eh_frame
+ *[0-9a-f]+: ........ ldp c29, c30, \[csp\], #64
+ *[0-9a-f]+: ........ ret c30
+
+#...
diff --git a/gas/testsuite/gas/aarch64/eh-frame-symbols.s b/gas/testsuite/gas/aarch64/eh-frame-symbols.s
new file mode 100644
index 0000000000000000000000000000000000000000..a10b59e034e15d048c5aef4ee1a82da9acd9e69e
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/eh-frame-symbols.s
@@ -0,0 +1,31 @@
+.section .eh_frame,"a"
+.type __EH_FRAME_BEGIN__, %object
+__EH_FRAME_BEGIN__:
+
+.text
+.type get_eh_frame_begin, %function
+get_eh_frame_begin:
+ .cfi_startproc purecap
+ stp c29, c30, [csp, -64]!
+ .cfi_def_cfa_offset 64
+ .cfi_offset 227, -64
+ .cfi_offset 228, -48
+ adrp c0, __EH_FRAME_BEGIN__
+ adrp c0, .eh_frame
+ add c0, c0, :lo12:__EH_FRAME_BEGIN__
+ add c0, c0, :lo12:.eh_frame
+ ldp c29, c30, [csp], 64
+ .cfi_restore 228
+ .cfi_restore 227
+ .cfi_def_cfa_offset 0
+ ret
+ .cfi_endproc
+
+.global _start
+.type _start, %function
+_start:
+ mov x0, #0
+ ret
+
+# .zero 0xff0 - 0x38 - 0x78
+.zero 0xff0 - 0x38
diff --git a/gas/write.c b/gas/write.c
index 054f27987d51f1732afdc81bbc9e19a95160c53f..5301bbd465048208c51f9b12fb6479c765c9a5f4 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -878,6 +878,28 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
continue;
}
+ /* Avoid adjusting a relocation against a symbol pointing into a
+ ".eh_frame" section in an ELF binary. The GNU bfd linker attempts
+ to de-duplicate CIE/FDE's in *output* .eh_frame sections in ELF
+ binaries and adjust any relocations pointing at the now removed
+ duplicate to point to the remaining entry.
+ Hence a symbol which had been adjusted to a section symbol plus
+ offset would end up pointing at something completely different.
+
+ We can not robustly match the exact linker-input sections that will
+ end up in the .eh_frame output section, since users may provide
+ their own linker scripts. However it does seem useful to avoid
+ transforming symbols in the sections that are expected to end up in
+ this linker output section. Rather than add a clause here to match
+ the current default linker script we use the same check based on
+ section name as is used in `gas/dw2gencfi.c` to check for .eh_frame
+ sections. */
+ if (IS_ELF
+ && strncmp (segment_name (symsec),
+ ".eh_frame", sizeof ".eh_frame" - 1) == 0
+ && segment_name (symsec)[9] != '_')
+ continue;
+
/* Never adjust a reloc against local symbol in a merge section
with non-zero addend. */
if ((symsec->flags & SEC_MERGE) != 0
We're disabling transformations of relocations against symbols like this
in the assembler when the relocation is against something in the GOT and
when the relocation is against something which generates a capability.
For entries in the GOT we disable this transformation since the GNU bfd
linker relies on indexing into its internal representation of the GOT
using symbols and does not distiinguish between entries using the same
symbol but different offsets. Hence transforming multiple symbols into
the same section symbol with different offsets would mean that at least
one will get an incorrect value.
Relocations which require the static linker to emit dynamic relocations
in order to generate capabilities (CAPINIT and capability relocations
into the GOT) require symbol information so that the dynamic linker can
put correct permissions and bounds on those relocations.
NOTE: We get to use an existing testcase for this change, but it showed
up something strange about objdump. One `adrp` instruction has changed
in the output so that it shows as pointing to a different location.
This happens to be an `objdump` quirk. Objdump looks at the relocation
associated with an address and attempts to include that relocation when
determining what address to print out. This mechanism has two problems,
one is that objdump does not account for the offset in that relocation
(only the symbol). Another is that on an object file (i.e. not a final
executable) the virtual memory address of all sections is zero. These
combined mean that the vma is miscalculated, and the translation from
vma to symbol is not injective. In other words: the extra change in
morello-ldst-reloc.d on top of switching the relocation symbols is in
order to account for an objdump bug and not a problem with this gas
change.
############### Attachment also inlined for ease of reply ###############
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index a1bd6e1a769d968ed0bdb2b3dca7bc87732cc498..c8373b311dd14f3c53ce4099ab1ffee28d360e8a 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -9382,13 +9382,37 @@ check_mapping_symbols (bfd * abfd ATTRIBUTE_UNUSED, asection * sec,
bfd_boolean
aarch64_fix_adjustable (struct fix *fixP)
{
- /* We need size information of the target symbols to initialise
- capabilities. */
- if (fixP->fx_r_type == BFD_RELOC_MORELLO_CAPINIT)
- return FALSE;
-
switch (fixP->fx_r_type)
{
+ /* The AArch64 GNU bfd linker can not handle 'symbol + offset' entries in the
+ GOT (it internally uses a symbol to reference a GOT slot). Hence we can't
+ emit any "section symbol + offset" relocations for the GOT. */
+ case BFD_RELOC_AARCH64_GOT_LD_PREL19:
+ case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
+ case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
+ case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
+ case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
+ case BFD_RELOC_AARCH64_LD64_GOTOFF_LO15:
+ case BFD_RELOC_AARCH64_LD32_GOTPAGE_LO14:
+ case BFD_RELOC_AARCH64_LD64_GOTPAGE_LO15:
+ case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
+ case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
+ case BFD_RELOC_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
+ case BFD_RELOC_AARCH64_LD_GOT_LO12_NC:
+ case BFD_RELOC_AARCH64_TLSIE_LD_GOTTPREL_LO12_NC:
+ return FALSE;
+
+ /* We need size information of the target symbols to initialise
+ capabilities. */
+ case BFD_RELOC_MORELLO_CAPINIT:
+ case BFD_RELOC_MORELLO_ADR_GOT_PAGE:
+ case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC:
+ return FALSE;
+
/* We need to retain symbol information when jumping between A64 and C64
states or between two C64 functions. In the C64 -> C64 situation it's
really only a corner case that breaks when symbols get replaced with
diff --git a/gas/testsuite/gas/aarch64/morello-ldst-reloc.d b/gas/testsuite/gas/aarch64/morello-ldst-reloc.d
index d2fb08ec9d13c28e6fa70f12c8f49f88fc37f34f..2199e90dd9091367ff6b8f237fa806ab642386ca 100644
--- a/gas/testsuite/gas/aarch64/morello-ldst-reloc.d
+++ b/gas/testsuite/gas/aarch64/morello-ldst-reloc.d
@@ -21,13 +21,13 @@ Disassembly of section \.text:
.*: R_AARCH64_ADD_ABS_LO12_NC ptr
.* <f1>:
- .*: 90800002 adrp c2, 0 <_start>
- .*: R_MORELLO_ADR_GOT_PAGE \.data\+0x10
+ .*: 90800002 adrp c2, 10 <add>
+ .*: R_MORELLO_ADR_GOT_PAGE cap
.*: c2400042 ldr c2, \[c2\]
- .*: R_MORELLO_LD128_GOT_LO12_NC \.data\+0x10
+ .*: R_MORELLO_LD128_GOT_LO12_NC cap
.*: 82600042 ldr c2, \[x2\]
- .*: R_MORELLO_LD128_GOT_LO12_NC \.data\+0x20
+ .*: R_MORELLO_LD128_GOT_LO12_NC ptr
.*: f9400042 ldr x2, \[c2\]
- .*: R_AARCH64_LD64_GOT_LO12_NC \.data\+0x20
+ .*: R_AARCH64_LD64_GOT_LO12_NC ptr
.*: 82600c42 ldr x2, \[x2\]
- .*: R_AARCH64_LD64_GOT_LO12_NC \.data\+0x20
+ .*: R_AARCH64_LD64_GOT_LO12_NC ptr
diff --git a/gas/testsuite/gas/aarch64/reloc-insn.d b/gas/testsuite/gas/aarch64/reloc-insn.d
index 0f3b4143d964ed08ef1d435fd518a7e2b13a80f8..8898a88bca0fe8f8e2755741c9d466636bf4aaff 100644
--- a/gas/testsuite/gas/aarch64/reloc-insn.d
+++ b/gas/testsuite/gas/aarch64/reloc-insn.d
@@ -157,9 +157,9 @@ Disassembly of section \.text:
18c: 39400001 ldrb w1, \[x0\]
190: d65f03c0 ret
194: f94001bc ldr x28, \[x13\]
- 194: R_AARCH64_LD64_GOTPAGE_LO15 \.data
+ 194: R_AARCH64_LD64_GOTPAGE_LO15 dummy
198: f9400000 ldr x0, \[x0\]
- 198: R_AARCH64_LD64_GOTOFF_LO15 .data
+ 198: R_AARCH64_LD64_GOTOFF_LO15 dummy
000000000000019c <llit>:
19c: deadf00d \.word 0xdeadf00d
Hi,
The calculation of OBJALLOC_ALIGN in include/objalloc.h ensures that
allocations are sufficiently aligned for doubles, but on CHERI
architectures it is possible that void * has a greater alignment
requirement than double.
Instead of deriving the alignment requirement from double alone, this
patch uses a union to compute the maximum alignment between double and
void *.
This fixes alignment faults seen when compiling the binutils for
pure-capability Morello. With this patch applied, the majority of
binutils tests pass when the binutils themselves are compiled for
purecap.
This patch is a backport of commit
a8af417a8a1559a3ebceb0c761cf26ebce5eab7f, initially upstreamed to
Morello GCC.
OK for morello branch?
Thanks,
Alex