]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Use htab->c64_rel more, do not use GOT_CAP
authorMatthew Malcomson <matthew.malcomson@arm.com>
Fri, 1 Jul 2022 10:48:52 +0000 (11:48 +0100)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Fri, 1 Jul 2022 10:48:52 +0000 (11:48 +0100)
Each symbol that has a reference in the GOT has an associated got_type.
For capabilities we currently have a new got_type of GOT_CAP for
capability entries in the GOT.

We do not allow capability entries in the GOT for an A64 (or hybrid)
binary, and only allow capability entries in the GOT for a purecap
binary.  Hence there is no need to maintain a per-symbol indication of
whether the associated GOT entry for this symbol is a capability or not.

There is already an existing flag on the hash table to indicate whether
the GOT contains capabilities or addresses.  We can replace every use of
the existing GOT_CAP with a check of this flag.

Doing such a transformation means we can not express an invalid state
(there is no longer any way to express a GOT which contains some
addresses and some capabilities).  It also solves a bug where we
introduce a PLT to be the canonical address of a function after having
seen a R_AARCH64_LDST128_ABS_LO12_NC relocation.  The existing manner of
deciding whether an entry in the GOT should be a capability or address
based on the relocation we generated it from could not work in a binary
when we only have this relocation.  It should be determined based on the
flags of the input object files we saw (i.e. are these purecap object
files or not).

N.b. this also fixes an observed problem that could have been fixed in
the existing regime.  In this case the JUMP_SLOT of a PLT entry added to
be the canonical address of a function which was addressed directly in
code (with both a Morello and AArch64 relocation) had got_type of
GOT_UNKNOWN (because it was simply not marked) and hence
elfNN_aarch64_create_small_pltn_entry was generating an AArch64
relocation because the GOT entry was not GOT_CAP.

This patch also adjusts the "should this GOT contain capabilities" flag
to report yes/no based on the EF_AARCH64_CHERI_PURECAP flag of the
inputs rather than based on whether we've seen any morello relocations
pointing into the GOT.
NOTE:  We do not remove the existing times where we set this flag based
on MORELLO relocations.  This is left for a future patch when we look
into the handling of hybrid code and the GOT.

N.b. this required two changes in the testsuite.
morello-capinit.d required updating since the size of the GOT section
was previously incorrectly calculated.  There is no GOT relocation in
this testcase, which meant that the existing method of finding the size
of the dummy first GOT entry was incorrect (gave the size of an AArch64
entry).  Since the size of the GOT is now different the PCC bounds is
now different, and we hence need to update the values checking for the
PCC bounds in this testcase.

We take this opportunity to make the testcase more robust by using the
new record/check testsuite feature.  This means the testcase now passes
on other targets (i.e. both bare-metal and for none-linux).

emit-relocs-morello.d had a minor change for the same reason.  Since the
alignment requirement of the GOT changed this changed the start position
too.  When the start position changed objdump decided not to output an
extra line of 0000000.

bfd/elfnn-aarch64.c
ld/testsuite/ld-aarch64/emit-relocs-morello.d
ld/testsuite/ld-aarch64/morello-capinit.d

index 76216f8f00125e8c22cacbe8b5610b4b1d105eb4..16447f15b05af3165b8bb2354437aa337ea3e304 100644 (file)
@@ -3000,7 +3000,6 @@ elfNN_aarch64_mkobject (bfd *abfd)
 #define GOT_TLS_GD     2
 #define GOT_TLS_IE     4
 #define GOT_TLSDESC_GD 8
-#define GOT_CAP        16
 
 #define GOT_TLS_GD_ANY_P(type) ((type & GOT_TLS_GD) || (type & GOT_TLSDESC_GD))
 
@@ -5915,7 +5914,7 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type)
 
     case BFD_RELOC_MORELLO_ADR_GOT_PAGE:
     case BFD_RELOC_MORELLO_LD128_GOT_LO12_NC:
-      return GOT_CAP;
+      return GOT_NORMAL;
 
     case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
     case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
@@ -5930,7 +5929,7 @@ aarch64_reloc_got_type (bfd_reloc_code_real_type r_type)
     case BFD_RELOC_MORELLO_TLSDESC_ADR_PAGE20:
     case BFD_RELOC_MORELLO_TLSDESC_CALL:
     case BFD_RELOC_MORELLO_TLSDESC_LD128_LO12:
-      return GOT_TLSDESC_GD | GOT_CAP;
+      return GOT_TLSDESC_GD | GOT_NORMAL;
 
     case BFD_RELOC_AARCH64_TLSDESC_ADD:
     case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12:
@@ -6775,8 +6774,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
                  || bfd_link_executable (info))
                {
                  /* This symbol is resolved locally.  */
-                 outrel.r_info = (elf_aarch64_hash_entry (h)->got_type
-                                  == GOT_CAP
+                 outrel.r_info = (globals->c64_rel
                                   ? ELFNN_R_INFO (0, MORELLO_R (IRELATIVE))
                                   : ELFNN_R_INFO (0, AARCH64_R (IRELATIVE)));
                  outrel.r_addend = (h->root.u.def.value
@@ -8827,6 +8825,15 @@ elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
        return TRUE;
 
       elf_elfheader (obfd)->e_flags = in_flags;
+      /* Determine if we are linking purecap or not based on the flags of the
+         input binaries.  Among other things this decides the size of GOT
+        entries.  */
+      if (in_flags & EF_AARCH64_CHERI_PURECAP)
+       {
+         struct elf_aarch64_link_hash_table *globals;
+         globals = elf_aarch64_hash_table (info);
+         globals->c64_rel = 1;
+       }
 
       if (bfd_get_arch (obfd) == bfd_get_arch (ibfd)
          && bfd_get_arch_info (obfd)->the_default)
@@ -9295,12 +9302,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
 
            case BFD_RELOC_MORELLO_CALL26:
            case BFD_RELOC_MORELLO_JUMP26:
-             /* For dynamic symbols record caller information so that we can
-                decide what kind of PLT stubs to emit.  */
-             if (h != NULL)
-               elf_aarch64_hash_entry (h)->got_type = GOT_CAP;
-             /* Fall through.  */
-
            case BFD_RELOC_AARCH64_ADD_LO12:
            case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
            case BFD_RELOC_MORELLO_ADR_GOT_PAGE:
@@ -9581,9 +9582,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            /* We will already have issued an error message if there
               is a TLS/non-TLS mismatch, based on the symbol type.
               So just combine any TLS types needed.  */
-           if (old_got_type != GOT_UNKNOWN && old_got_type != GOT_NORMAL
-               && got_type != GOT_NORMAL && old_got_type != GOT_CAP
-               && got_type != GOT_CAP)
+           if (old_got_type != GOT_UNKNOWN && old_got_type != GOT_NORMAL &&
+               got_type != GOT_NORMAL)
              got_type |= old_got_type;
 
            /* If the symbol is accessed by both IE and GD methods, we
@@ -9593,13 +9593,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
            if ((got_type & GOT_TLS_IE) && GOT_TLS_GD_ANY_P (got_type))
              got_type &= ~ (GOT_TLSDESC_GD | GOT_TLS_GD);
 
-           /* Prefer the capability reference.  */
-           if ((old_got_type & GOT_CAP) && (got_type & GOT_NORMAL))
-             {
-               got_type &= ~GOT_NORMAL;
-               got_type |= GOT_CAP;
-             }
-
            if (old_got_type != got_type)
              {
                if (h != NULL)
@@ -9623,9 +9616,6 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
        case BFD_RELOC_MORELLO_CALL26:
        case BFD_RELOC_MORELLO_JUMP26:
          htab->c64_rel = 1;
-         if (h != NULL)
-           elf_aarch64_hash_entry (h)->got_type = GOT_CAP;
-
          /* Fall through.  */
        case BFD_RELOC_AARCH64_CALL26:
        case BFD_RELOC_AARCH64_JUMP26:
@@ -10221,8 +10211,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
       if (got_type == GOT_UNKNOWN)
        {
        }
-      else if (got_type == GOT_NORMAL
-              || got_type == GOT_CAP)
+      else if (got_type == GOT_NORMAL)
        {
          h->got.offset = htab->root.sgot->size;
          htab->root.sgot->size += GOT_ENTRY_SIZE (htab);
@@ -10235,11 +10224,11 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
               && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
              /* Any capability relocations required in a dynamic binary
                 should go in the srelgot.  */
-             || ((got_type == GOT_CAP) && dyn))
+             || (htab->c64_rel && dyn))
            {
              htab->root.srelgot->size += RELOC_SIZE (htab);
            }
-         else if (bfd_link_executable (info) && (got_type == GOT_CAP))
+         else if (bfd_link_executable (info) && htab->c64_rel)
            {
              /* If we have a capability relocation that is not handled by the
                 case above then this must be a statically linked executable.  */
@@ -10279,7 +10268,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
                  || WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h)
                  /* On Morello support only TLSDESC_GD to TLSLE relaxation;
                     for everything else we must emit a dynamic relocation.  */
-                 || got_type & GOT_CAP))
+                 || htab->c64_rel))
            {
              if (got_type & GOT_TLSDESC_GD)
                {
@@ -10562,8 +10551,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd,
                }
 
              if (got_type & GOT_TLS_IE
-                 || got_type & GOT_NORMAL
-                 || got_type & GOT_CAP)
+                 || got_type & GOT_NORMAL)
                {
                  locals[i].got_offset = htab->root.sgot->size;
                  htab->root.sgot->size += GOT_ENTRY_SIZE (htab);
@@ -10586,17 +10574,16 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd,
                    htab->root.srelgot->size += RELOC_SIZE (htab) * 2;
 
                  if (got_type & GOT_TLS_IE
-                     || got_type & GOT_NORMAL
-                     || got_type & GOT_CAP)
+                     || got_type & GOT_NORMAL)
                    htab->root.srelgot->size += RELOC_SIZE (htab);
                }
              /* Static binary; put relocs into srelcaps.  */
              else if (bfd_link_executable (info)
                       && !htab->root.dynamic_sections_created
-                      && (got_type & GOT_CAP))
+                      && htab->c64_rel)
                htab->srelcaps->size += RELOC_SIZE (htab);
              /* Else capability relocation needs to go into srelgot.  */
-             else if (got_type & GOT_CAP)
+             else if (htab->c64_rel)
                htab->root.srelgot->size += RELOC_SIZE (htab);
            }
          else
@@ -10917,7 +10904,7 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
     {
       /* If an STT_GNU_IFUNC symbol is locally defined, generate
         R_AARCH64_IRELATIVE instead of R_AARCH64_JUMP_SLOT.  */
-      rela.r_info = (elf_aarch64_hash_entry (h)->got_type == GOT_CAP
+      rela.r_info = (htab->c64_rel
                     ? ELFNN_R_INFO (0, MORELLO_R (IRELATIVE))
                     : ELFNN_R_INFO (0, AARCH64_R (IRELATIVE)));
       rela.r_addend = (h->root.u.def.value
@@ -10927,7 +10914,7 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
   else
     {
       /* Fill in the entry in the .rela.plt section.  */
-      rela.r_info = (elf_aarch64_hash_entry (h)->got_type == GOT_CAP
+      rela.r_info = (htab->c64_rel
                     ? ELFNN_R_INFO (h->dynindx, MORELLO_R (JUMP_SLOT))
                     : ELFNN_R_INFO (h->dynindx, AARCH64_R (JUMP_SLOT)));
       rela.r_addend = 0;
@@ -11047,11 +11034,8 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
        }
     }
 
-  bfd_boolean is_c64 = elf_aarch64_hash_entry (h)->got_type == GOT_CAP;
-
   if (h->got.offset != (bfd_vma) - 1
-      && (elf_aarch64_hash_entry (h)->got_type == GOT_NORMAL
-         || elf_aarch64_hash_entry (h)->got_type == GOT_CAP)
+      && elf_aarch64_hash_entry (h)->got_type == GOT_NORMAL
       /* Undefined weak symbol in static PIE resolves to 0 without
         any dynamic relocations.  */
       && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
@@ -11104,7 +11088,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
          bfd_vma value = h->root.u.def.value
            + h->root.u.def.section->output_section->vma
            + h->root.u.def.section->output_offset;
-         if (is_c64)
+         if (htab->c64_rel)
            {
              rela.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE));
              bfd_vma base_value = 0;
@@ -11127,7 +11111,8 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
          bfd_put_NN (output_bfd, (bfd_vma) 0,
                      htab->root.sgot->contents + h->got.offset);
          rela.r_info = ELFNN_R_INFO (h->dynindx,
-                                     (is_c64 ? MORELLO_R (GLOB_DAT)
+                                     (htab->c64_rel
+                                      ? MORELLO_R (GLOB_DAT)
                                       : AARCH64_R (GLOB_DAT)));
          rela.r_addend = 0;
        }
index 4613b776edbe5b900386da94b450b3f16d416440..1a9be9b60bb9fcf15d74e65e9ebe224ac3d769b8 100644 (file)
@@ -21,7 +21,7 @@ Disassembly of section .got:
 
 .* <.got>:
 .*:    [0-9a-f]+       .*
-.*:    00000000        .*
+       \.\.\.
 
 Disassembly of section .data:
 
index 0050df311ac03275d00d69bb57ad7ab48f92eeea..edb0f42d9eeb83e4cd81018ab3de1932d07bbb45 100644 (file)
@@ -1,6 +1,6 @@
-# This testsuite is used largely to check our handling of linker script defined
+# This testcase is used largely to check our handling of linker script defined
 # symbols.  In the general case we want to be able to access the entire output
-# section following this symbol (i.e. we treat this symbol as a start symbol).
+# section following the symbol (i.e. we treat the symbol as a start symbol).
 #
 # There is an exception for a symbol that points into an executable section --
 # we want this to have the bounds of the PCC as we see it.
@@ -8,6 +8,12 @@
 # There is also an exception for a symbol which is *outside* of an output
 # section where we have a compatibility hack to try and guess whether it
 # represents the start of the next section or end of the previous section.
+#
+# Rather than check the PCC bounds exactly, we check that the PCC bounds are
+# consistent for all symbols pointing into the text section (which allows for
+# variation between aarch64-linux-gnu and aarch64-none-elf coming from an extra
+# GNU_HASH section or a differing start position of the text causing a
+# differing bounds action).
 #source: morello-capinit.s
 #as: -march=morello+c64
 #ld: -static -pie -T morello-capinit.ld
@@ -22,35 +28,37 @@ Disassembly of section \.inspectionsection:
 .*:    [0-9a-f]+       .*
                        .*: R_MORELLO_RELATIVE  \*ABS\*
 .*:    00000000        .*
-.*:    00000278        .*
+#record: PCC_BOUNDS
+.*:    ([0-9a-f]+)     .*
 .*:    04000000        .*
 
+#check: PCC_SIZE string tolower $PCC_BOUNDS
 [0-9a-f]+ <ct_start>:
 .*:    [0-9a-f]+       .*
                        .*: R_MORELLO_RELATIVE  \*ABS\*
 .*:    00000000        .*
-.*:    00000278        .*
+.*:    PCC_SIZE        .*
 .*:    04000000        .*
 
 [0-9a-f]+ <ct1_start>:
 .*:    [0-9a-f]+       .*
                        .*: R_MORELLO_RELATIVE  \*ABS\*\+0x[0-9a-f]+
 .*:    00000000        .*
-.*:    00000278        .*
+.*:    PCC_SIZE        .*
 .*:    04000000        .*
 
 [0-9a-f]+ <ct1_end>:
 .*:    [0-9a-f]+       .*
                        .*: R_MORELLO_RELATIVE  \*ABS\*\+0x[0-9a-f]+
 .*:    00000000        .*
-.*:    00000278        .*
+.*:    PCC_SIZE        .*
 .*:    04000000        .*
 
 [0-9a-f]+ <ct_end>:
 .*:    [0-9a-f]+       .*
                        .*: R_MORELLO_RELATIVE  \*ABS\*\+0x[0-9a-f]+
 .*:    00000000        .*
-.*:    00000278        .*
+.*:    PCC_SIZE        .*
 .*:    04000000        .*
 
 [0-9a-f]+ <cd_outer_start>: