if (outrel.r_offset & 0xf)
return bfd_reloc_overflow;
- bfd_reloc_status_type ret;
-
- ret = c64_fixup_frag (input_bfd, info, bfd_r_type, sym, h, sym_sec,
- input_section, hit_data + 8, value,
- signed_addend, rel->r_offset);
-
- if (ret != bfd_reloc_continue)
- return ret;
-
outrel.r_addend = signed_addend;
- value |= (h != NULL ? h->target_internal : sym->st_target_internal);
- /* Emit a dynamic relocation if we are building PIC. */
+ /* Emit a dynamic relocation if we are handling a symbol which the
+ dynamic linker will be told about. */
if (h != NULL
&& h->dynindx != -1
- && bfd_link_pic (info)
+ && globals->root.dynamic_sections_created
&& !SYMBOL_REFERENCES_LOCAL (info, h))
- outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
+ {
+ outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
+ /* Dynamic symbols will be handled by the dynamic loader. Hence
+ there is no need to fill a fragment with a value even if there
+ is a value that we would use assuming no interception. */
+ value = 0;
+ }
else
- outrel.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE));
-
- /* Symbols without size information get bounds to the
- whole section: adjust the base of the capability to the
- start of the section and set the addend to obtain the
- correct address for the symbol. */
- bfd_vma new_value;
- if (c64_symbol_adjust (h, value, sym_sec, info, &new_value))
{
- outrel.r_addend += (value - new_value);
- value = new_value;
+ /* This relocation will point into the object we are building
+ (either because this is a statically linked executable and
+ hence there is only one object it could point at, or because
+ we know it will resolve locally even though this is
+ dynamically linked).
+
+ Hence we want to emit a RELATIVE relocation rather than a
+ CAPINIT one. */
+ bfd_reloc_status_type ret;
+
+ value |= (h != NULL ? h->target_internal : sym->st_target_internal);
+ ret = c64_fixup_frag (input_bfd, info, bfd_r_type, sym, h, sym_sec,
+ input_section, hit_data + 8, value,
+ signed_addend, rel->r_offset);
+
+ if (ret != bfd_reloc_continue)
+ return ret;
+
+ outrel.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE));
+
+ /* Symbols without size information get bounds to the
+ whole section: adjust the base of the capability to the
+ start of the section and set the addend to obtain the
+ correct address for the symbol. */
+ bfd_vma new_value;
+ if (c64_symbol_adjust (h, value, sym_sec, info, &new_value))
+ {
+ outrel.r_addend += (value - new_value);
+ value = new_value;
+ }
}
asection *s = globals->srelcaps;
return [format %x [expr "0x$result + 1 - 0x$base"]];
}
+# Return the hexadecimal addition of the two given values. Values should be
+# provided in hexadecimal without the leading 0x prefix.
+#
+# Used in a testsuite to check that the combination of some ADRP/ADD constants
+# do indeed point at a variable later on in the dump.
+proc aarch64_page_plus_offset { page offset } {
+ return [format %x [expr "0x$page + 0x$offset"] ];
+}
+
set eh-frame-merge-lp64 [list [list "EH Frame merge" \
[concat "-m " [aarch64_choose_lp64_emul] \
" -Ttext 0x8000"] \
run_dump_test_lp64 "morello-dynamic-link-rela-dyn"
run_dump_test_lp64 "morello-dynamic-link-rela-dyn2"
run_dump_test_lp64 "morello-dynamic-local-got"
+ run_dump_test_lp64 "morello-funcptr-in-code"
+ run_dump_test_lp64 "morello-funcptr-through-data"
+ run_dump_test_lp64 "morello-funcptr-through-data-pie"
+ run_dump_test_lp64 "morello-funcptr-code-and-data"
+ run_dump_test_lp64 "morello-dataptr-in-code"
+ run_dump_test_lp64 "morello-dataptr-through-data"
+ run_dump_test_lp64 "morello-dataptr-through-data-pie"
+ run_dump_test_lp64 "morello-dataptr-code-and-data"
}
run_dump_test_lp64 "morello-static-got"
.*: 00000000 .*
.* <cap>:
-.*: [0-9a-f]+ .*
+ \.\.\.
.*: R_MORELLO_CAPINIT str
-.*: 00000000 .*
-.*: 0000001b .*
-.*: 02000000 .*
.* <cap2>:
- ...
+ \.\.\.
.*: R_MORELLO_CAPINIT str2
.*: 00000000 .*
.* <cap>:
-.*: [0-9a-f]+ .*
+ \.\.\.
.*: R_MORELLO_CAPINIT str
-.*: 00000000 .*
-.*: 0000001b .*
-.*: 02000000 .*
.* <cap2>:
- ...
+ \.\.\.
.*: R_MORELLO_CAPINIT str2
--- /dev/null
+# Want to double-check that when creating a PDE which loads a data pointer
+# in an external library using an adrp/ldr code sequence and also via a CAPINIT
+# relocation, we generate both a COPY relocation and a CAPINIT relocation.
+#
+# We want to make sure the COPY relocation is used by the text. We can not
+# check that the dynamic loader would initialize the CAPINIT relocation with
+# the address of that COPY relocation, so that's left.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .data -j .bss -j .text
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+.* <_start>:
+#record: PAGE
+.*: .* adrp c0, ([0-9a-f]*).*
+#record: OFFSET
+.*: .* add c0, c0, #0x([0-9a-f]*)
+.*: .* ldr w0, \[c0\]
+.*: .* ret c30
+
+Disassembly of section \.data:
+#...
+ .*: R_MORELLO_CAPINIT var
+
+Disassembly of section \.bss:
+
+#check: VAR_LOCATION aarch64_page_plus_offset $PAGE $OFFSET
+0*VAR_LOCATION <var>:
+ \.\.\.
+ VAR_LOCATION: R_AARCH64_COPY var
+
--- /dev/null
+ .arch morello+crc+c64
+ .text
+ .p2align 4,,11
+ .global _start
+ .type _start, %function
+_start:
+ .cfi_startproc purecap
+ adrp c0, var
+ add c0, c0, #:lo12:var
+ ldr w0, [c0]
+ ret
+ .cfi_endproc
+ .size _start, .-_start
+ .data
+varptr:
+ .chericap var
--- /dev/null
+# Want to double-check that when creating a PDE which references a data pointer
+# in an external library in code with an adrp/add, we generate a COPY
+# relocation and access that the data said relocation will initialize.
+#
+# We check this by ensuring that there is a new `var` symbol in the .bss of the
+# PDE, that the adrp/add addresses point to that symbol, and that there is a
+# COPY relocation at that symbol for its initialisation.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .bss -j .text
+
+.*: file format .*
+
+
+Disassembly of section \.text:
+
+.* <_start>:
+#record: PAGE
+.*: .* adrp c0, ([0-9a-f]*).*
+#record: OFFSET
+.*: .* add c0, c0, #0x([0-9a-f]*)
+.*: .* ldr w0, \[c0\]
+.*: .* ret c30
+
+Disassembly of section \.bss:
+
+#check: VAR_LOCATION aarch64_page_plus_offset $PAGE $OFFSET
+0*VAR_LOCATION <var>:
+ \.\.\.
+ VAR_LOCATION: R_AARCH64_COPY var
+
--- /dev/null
+ .arch morello+crc+c64
+ .text
+ .p2align 4,,11
+ .global _start
+ .type _start, %function
+_start:
+ .cfi_startproc purecap
+ adrp c0, var
+ add c0, c0, #:lo12:var
+ ldr w0, [c0]
+ ret
+ .cfi_endproc
+ .size _start, .-_start
--- /dev/null
+# Want to double-check that when creating a PIE which loads a data pointer
+# in an external library using a CAPINIT relocation we end up with a
+# straight-forward CAPINIT relocation in the final binary requesting the
+# dynamic loader to provide a capability pointing to that bit of data.
+#source: morello-dataptr-through-data.s
+#as: -march=morello+c64
+#ld: -pie tmpdir/morello-dynamic-relocs.so
+#readelf: --relocs
+
+Relocation section '\.rela\.dyn' at offset .* contains 1 entry:
+ Offset Info Type Sym\. Value Sym\. Name \+ Addend
+.* .* R_MORELLO_CAPINIT .* var \+ 0
--- /dev/null
+# Want to double-check that when creating a PDE which loads a data pointer
+# in an external library using a CAPINIT relocation we end up with a
+# straight-forward CAPINIT relocation in the final binary requesting the
+# dynamic loader to provide a capability pointing to that bit of data.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#readelf: --relocs
+
+Relocation section '\.rela\.dyn' at offset .* contains 1 entry:
+ Offset Info Type Sym\. Value Sym\. Name \+ Addend
+.* .* R_MORELLO_CAPINIT .* var \+ 0
--- /dev/null
+ .arch morello+crc+c64
+ .text
+ .p2align 4,,11
+ .global _start
+ .type _start, %function
+_start:
+ .cfi_startproc purecap
+ ret
+ .cfi_endproc
+ .size _start, .-_start
+ .data
+varptr:
+ .chericap var
.arch morello+crc+c64
.text
+ .p2align 4,,11
+ .global memcpy
+ .type memcpy,%function
+memcpy:
+ ret
+ .size memcpy, .-memcpy
.global var
.bss
.align 2
--- /dev/null
+# Want to double-check that when creating a PDE which references a function
+# pointer in an external library with a CAPINIT and also references the
+# function pointer in code with an adrp/add, we generate a CAPINIT
+# entry in that PDE and also generate a PLT entry.
+# We check this by ensuring that there is a memcpy@plt entry in the PLT, that
+# there is the associated MORELLO jump slot relocation in the .got.plt, and
+# there is a CAPINIT relocation.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .data -j .got.plt
+
+.*: file format .*
+
+Disassembly of section \.plt:
+#...
+.* <memcpy@plt>:
+#...
+Disassembly of section \.got\.plt:
+#...
+.*: R_MORELLO_JUMP_SLOT memcpy
+#...
+Disassembly of section \.data:
+
+.* <p>:
+ \.\.\.
+ .*: R_MORELLO_CAPINIT memcpy
--- /dev/null
+ .arch morello+crc+c64
+ .text
+ .p2align 4,,11
+ .global _start
+ .type _start, %function
+_start:
+ .cfi_startproc purecap
+ adrp c0, memcpy
+ ldr c0, [c0, #:lo12:memcpy]
+ ldr w0, [c0]
+ ret
+ .cfi_endproc
+ .size _start, .-_start
+ .global p
+ .section .data.rel,"aw"
+ .align 4
+ .type p, %object
+ .size p, 16
+p:
+ .chericap memcpy
+
--- /dev/null
+# Want to double-check that when creating a PDE which loads a function pointer
+# in an external library using an adrp/ldr code sequence, we generate a PLT
+# entry in that PDE and use that PLT entry as the address that is loaded in the
+# code.
+# We check this by ensuring that there is a memcpy@plt entry in the PLT, and
+# that the .got.plt has a MORELLO jump slot relocation in it.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .got.plt
+
+.*: file format .*
+
+
+Disassembly of section \.plt:
+#...
+.* <memcpy@plt>:
+#...
+Disassembly of section \.got\.plt:
+#...
+.*: R_MORELLO_JUMP_SLOT memcpy
+#pass
--- /dev/null
+ .text
+ .p2align 4,,11
+ .global _start
+ .type _start, %function
+_start:
+ .cfi_startproc purecap
+ adrp c0, memcpy
+ add c0, c0, #:lo12:memcpy
+ ldr w0, [c0]
+ ret
+ .cfi_endproc
+ .size _start, .-_start
+
--- /dev/null
+# Want to double-check that when creating a PIE which references a function
+# pointer in an external library with a CAPINIT and does not reference the
+# function pointer in code with an adrp/add, we generate a CAPINIT
+# entry in that PIE and do not generate a PLT entry.
+# We check this by ensuring that there is no memcpy@plt entry in the PLT, and
+# by checking there is a CAPINIT relocation.
+#source: morello-funcptr-through-data.s
+#as: -march=morello+c64
+#ld: -pie tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .data
+
+.*: file format .*
+
+Disassembly of section \.data:
+
+.* <p>:
+ \.\.\.
+ .*: R_MORELLO_CAPINIT memcpy
+
--- /dev/null
+# Want to double-check that when creating a PDE which references a function
+# pointer in an external library with a CAPINIT and does not reference the
+# function pointer in code with an adrp/add, we generate a CAPINIT
+# entry in that PDE and do not generate a PLT entry.
+# We check this by ensuring that there is no memcpy@plt entry in the PLT, and
+# by checking there is a CAPINIT relocation.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .data
+
+.*: file format .*
+
+Disassembly of section \.data:
+
+.* <p>:
+ \.\.\.
+ .*: R_MORELLO_CAPINIT memcpy
--- /dev/null
+ .arch morello+crc+c64
+ .text
+ .p2align 4,,11
+ .global _start
+ .type _start, %function
+_start:
+ .cfi_startproc purecap
+ ret
+ .cfi_endproc
+ .size _start, .-_start
+ .global p
+ .section .data.rel,"aw"
+ .align 4
+ .type p, %object
+ .size p, 16
+p:
+ .chericap memcpy
+