Make bfd_byte an int8_t, flagword a uint32_t
[binutils-gdb.git] / bfd / elf64-x86-64.c
index 2ae8dffba0f0f980f16931ad7bbc41db0a0886d6..dd987ee011bb8afac8b05775059de03a35fe1834 100644 (file)
@@ -1,5 +1,5 @@
 /* X86-64 specific support for ELF
-   Copyright (C) 2000-2022 Free Software Foundation, Inc.
+   Copyright (C) 2000-2023 Free Software Foundation, Inc.
    Contributed by Jan Hubicka <jh@suse.cz>.
 
    This file is part of BFD, the Binary File Descriptor library.
@@ -22,6 +22,7 @@
 #include "elfxx-x86.h"
 #include "dwarf2.h"
 #include "libiberty.h"
+#include "sframe.h"
 
 #include "opcode/i386.h"
 
@@ -388,7 +389,8 @@ elf_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
       default:
        return false;
 
-      case 124:                /* sizeof(struct elf_prpsinfo) on Linux/x32 */
+      case 124:
+       /* sizeof (struct elf_external_linux_prpsinfo32_ugid16).  */
        elf_tdata (abfd)->core->pid
          = bfd_get_32 (abfd, note->descdata + 12);
        elf_tdata (abfd)->core->program
@@ -397,7 +399,18 @@ elf_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
          = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
        break;
 
-      case 136:                /* sizeof(struct elf_prpsinfo) on Linux/x86_64 */
+    case 128:
+       /* sizeof (struct elf_external_linux_prpsinfo32_ugid32).  */
+       elf_tdata (abfd)->core->pid
+         = bfd_get_32 (abfd, note->descdata + 12);
+       elf_tdata (abfd)->core->program
+         = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16);
+       elf_tdata (abfd)->core->command
+         = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80);
+       break;
+
+      case 136:
+       /* sizeof (struct elf_prpsinfo) on Linux/x86_64.  */
        elf_tdata (abfd)->core->pid
          = bfd_get_32 (abfd, note->descdata + 24);
        elf_tdata (abfd)->core->program
@@ -818,6 +831,87 @@ static const bfd_byte elf_x86_64_eh_frame_non_lazy_plt[] =
   DW_CFA_nop, DW_CFA_nop, DW_CFA_nop
 };
 
+static const sframe_frame_row_entry elf_x86_64_sframe_null_fre =
+{
+  0,
+  {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes.  */
+  SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info.  */
+};
+
+/* .sframe FRE covering the .plt section entry.  */
+static const sframe_frame_row_entry elf_x86_64_sframe_plt0_fre1 =
+{
+  0, /* SFrame FRE start address.  */
+  {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes.  */
+  SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info.  */
+};
+
+/* .sframe FRE covering the .plt section entry.  */
+static const sframe_frame_row_entry elf_x86_64_sframe_plt0_fre2 =
+{
+  6, /* SFrame FRE start address.  */
+  {24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes.  */
+  SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info.  */
+};
+
+/* .sframe FRE covering the .plt section entry.  */
+static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre1 =
+{
+  0, /* SFrame FRE start address.  */
+  {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes.  */
+  SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info.  */
+};
+
+/* .sframe FRE covering the .plt section entry.  */
+static const sframe_frame_row_entry elf_x86_64_sframe_pltn_fre2 =
+{
+  11, /* SFrame FRE start address.  */
+  {16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes.  */
+  SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info.  */
+};
+
+/* .sframe FRE covering the second .plt section entry.  */
+static const sframe_frame_row_entry elf_x86_64_sframe_sec_pltn_fre1 =
+{
+  0, /* SFrame FRE start address.  */
+  {8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* 12 bytes.  */
+  SFRAME_V1_FRE_INFO (SFRAME_BASE_REG_SP, 1, SFRAME_FRE_OFFSET_1B) /* FRE info.  */
+};
+
+/* SFrame helper object for non-lazy PLT.  Also used for IBT enabled PLT.  */
+static const struct elf_x86_sframe_plt elf_x86_64_sframe_non_lazy_plt =
+{
+  LAZY_PLT_ENTRY_SIZE,
+  2, /* Number of FREs for PLT0.  */
+  /* Array of SFrame FREs for plt0.  */
+  { &elf_x86_64_sframe_plt0_fre1, &elf_x86_64_sframe_plt0_fre2 },
+  LAZY_PLT_ENTRY_SIZE,
+  1, /* Number of FREs for PLTn.  */
+  /* Array of SFrame FREs for plt.  */
+  { &elf_x86_64_sframe_sec_pltn_fre1, &elf_x86_64_sframe_null_fre },
+  0,
+  0, /* There is no second PLT necessary.  */
+  { &elf_x86_64_sframe_null_fre }
+};
+
+/* SFrame helper object for lazy PLT.  Also used for IBT enabled PLT.  */
+static const struct elf_x86_sframe_plt elf_x86_64_sframe_plt =
+{
+  LAZY_PLT_ENTRY_SIZE,
+  2, /* Number of FREs for PLT0.  */
+  /* Array of SFrame FREs for plt0.  */
+  { &elf_x86_64_sframe_plt0_fre1, &elf_x86_64_sframe_plt0_fre2 },
+  LAZY_PLT_ENTRY_SIZE,
+  2, /* Number of FREs for PLTn.  */
+  /* Array of SFrame FREs for plt.  */
+  { &elf_x86_64_sframe_pltn_fre1, &elf_x86_64_sframe_pltn_fre2 },
+  NON_LAZY_PLT_ENTRY_SIZE,
+  1, /* Number of FREs for PLTn for second PLT.  */
+  /* FREs for second plt (stack trace info for .plt.got is
+     identical).  Used when IBT or non-lazy PLT is in effect.  */
+  { &elf_x86_64_sframe_sec_pltn_fre1 }
+};
+
 /* These are the standard parameters.  */
 static const struct elf_x86_lazy_plt_layout elf_x86_64_lazy_plt =
   {
@@ -971,7 +1065,6 @@ static const struct elf_x86_non_lazy_plt_layout elf_x32_non_lazy_ibt_plt =
     sizeof (elf_x86_64_eh_frame_non_lazy_plt) /* eh_frame_plt_size */
   };
 
-
 static bool
 elf64_x86_64_elf_object_p (bfd *abfd)
 {
@@ -1160,7 +1253,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
          if (largepic)
            return r_type == R_X86_64_PLTOFF64;
          else if (indirect_call)
-           return r_type == R_X86_64_GOTPCRELX;
+           return (r_type == R_X86_64_GOTPCRELX || r_type == R_X86_64_GOTPCREL);
          else
            return (r_type == R_X86_64_PC32 || r_type == R_X86_64_PLT32);
        }
@@ -2116,7 +2209,6 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
          break;
 
        case R_X86_64_PLT32:
-       case R_X86_64_PLT32_BND:
          /* This symbol requires a procedure linkage table entry.  We
             actually build the entry in adjust_dynamic_symbol,
             because this might be a case of linking PIC code which is
@@ -2175,7 +2267,6 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
        case R_X86_64_PC8:
        case R_X86_64_PC16:
        case R_X86_64_PC32:
-       case R_X86_64_PC32_BND:
        case R_X86_64_PC64:
        case R_X86_64_64:
        pointer:
@@ -2208,8 +2299,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struct bfd_link_info *info,
                        }
                    }
                }
-             else if (r_type != R_X86_64_PC32_BND
-                      && r_type != R_X86_64_PC64)
+             else if (r_type != R_X86_64_PC64)
                {
                  /* At run-time, R_X86_64_64 can be resolved for both
                     x86-64 and x32. But R_X86_64_32 and R_X86_64_32S
@@ -2824,10 +2914,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
                }
              /* FALLTHROUGH */
            case R_X86_64_PC32:
-           case R_X86_64_PC32_BND:
            case R_X86_64_PC64:
            case R_X86_64_PLT32:
-           case R_X86_64_PLT32_BND:
              goto do_relocation;
            }
        }
@@ -3091,7 +3179,6 @@ elf_x86_64_relocate_section (bfd *output_bfd,
          break;
 
        case R_X86_64_PLT32:
-       case R_X86_64_PLT32_BND:
          /* Relocation is to the entry for this symbol in the
             procedure linkage table.  */
 
@@ -3146,7 +3233,6 @@ elf_x86_64_relocate_section (bfd *output_bfd,
        case R_X86_64_PC8:
        case R_X86_64_PC16:
        case R_X86_64_PC32:
-       case R_X86_64_PC32_BND:
          /* Don't complain about -fPIC if the symbol is undefined when
             building executable unless it is unresolved weak symbol,
             references a dynamic definition in PIE or -z nocopyreloc
@@ -4845,6 +4931,8 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
   const struct elf_x86_non_lazy_plt_layout *non_lazy_bnd_plt;
   const struct elf_x86_lazy_plt_layout *lazy_ibt_plt;
   const struct elf_x86_non_lazy_plt_layout *non_lazy_ibt_plt;
+  const struct elf_x86_lazy_plt_layout *x32_lazy_ibt_plt;
+  const struct elf_x86_non_lazy_plt_layout *x32_non_lazy_ibt_plt;
   asection *plt;
   enum elf_x86_plt_type plt_type;
   struct elf_x86_plt plts[] =
@@ -4876,18 +4964,24 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
     {
       lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt;
       non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt;
+      x32_lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
+      x32_non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
     }
   else
     {
       lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
       non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
+      x32_lazy_ibt_plt = NULL;
+      x32_non_lazy_ibt_plt = NULL;
     }
 
   count = 0;
   for (j = 0; plts[j].name != NULL; j++)
     {
       plt = bfd_get_section_by_name (abfd, plts[j].name);
-      if (plt == NULL || plt->size == 0)
+      if (plt == NULL
+         || plt->size == 0
+         || (plt->flags & SEC_HAS_CONTENTS) == 0)
        continue;
 
       /* Get the PLT section contents.  */
@@ -4906,7 +5000,21 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
                       lazy_plt->plt0_got1_offset) == 0)
              && (memcmp (plt_contents + 6, lazy_plt->plt0_entry + 6,
                          2) == 0))
-           plt_type = plt_lazy;
+           {
+             if (x32_lazy_ibt_plt != NULL
+                 && (memcmp (plt_contents
+                             + x32_lazy_ibt_plt->plt_entry_size,
+                             x32_lazy_ibt_plt->plt_entry,
+                             x32_lazy_ibt_plt->plt_got_offset) == 0))
+               {
+                 /* The fist entry in the x32 lazy IBT PLT is the same
+                    as the lazy PLT.  */
+                 plt_type = plt_lazy | plt_second;
+                 lazy_plt = x32_lazy_ibt_plt;
+               }
+             else
+               plt_type = plt_lazy;
+           }
          else if (lazy_bnd_plt != NULL
                   && (memcmp (plt_contents, lazy_bnd_plt->plt0_entry,
                               lazy_bnd_plt->plt0_got1_offset) == 0)
@@ -4956,6 +5064,16 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
              plt_type = plt_second;
              non_lazy_plt = non_lazy_ibt_plt;
            }
+         else if (x32_non_lazy_ibt_plt != NULL
+                  && plt->size >= x32_non_lazy_ibt_plt->plt_entry_size
+                  && (memcmp (plt_contents,
+                              x32_non_lazy_ibt_plt->plt_entry,
+                              x32_non_lazy_ibt_plt->plt_got_offset) == 0))
+           {
+             /* Match x32 IBT PLT.  */
+             plt_type = plt_second;
+             non_lazy_plt = x32_non_lazy_ibt_plt;
+           }
        }
 
       if (plt_type == plt_unknown)
@@ -5206,26 +5324,25 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
   htab = elf_x86_hash_table (info, bed->target_id);
   if (!htab)
     abort ();
-  if (htab->params->bndplt)
-    {
-      init_table.lazy_plt = &elf_x86_64_lazy_bnd_plt;
-      init_table.non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
-    }
-  else
-    {
-      init_table.lazy_plt = &elf_x86_64_lazy_plt;
-      init_table.non_lazy_plt = &elf_x86_64_non_lazy_plt;
-    }
+
+  init_table.lazy_plt = &elf_x86_64_lazy_plt;
+  init_table.non_lazy_plt = &elf_x86_64_non_lazy_plt;
+
+  init_table.lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
+  init_table.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
 
   if (ABI_64_P (info->output_bfd))
     {
-      init_table.lazy_ibt_plt = &elf_x86_64_lazy_ibt_plt;
-      init_table.non_lazy_ibt_plt = &elf_x86_64_non_lazy_ibt_plt;
+      init_table.sframe_lazy_plt = &elf_x86_64_sframe_plt;
+      init_table.sframe_non_lazy_plt = &elf_x86_64_sframe_non_lazy_plt;
+      init_table.sframe_lazy_ibt_plt = &elf_x86_64_sframe_plt;
+      init_table.sframe_non_lazy_ibt_plt = &elf_x86_64_sframe_non_lazy_plt;
     }
   else
     {
-      init_table.lazy_ibt_plt = &elf_x32_lazy_ibt_plt;
-      init_table.non_lazy_ibt_plt = &elf_x32_non_lazy_ibt_plt;
+      /* SFrame is not supported for non AMD64.  */
+      init_table.sframe_lazy_plt = NULL;
+      init_table.sframe_non_lazy_plt = NULL;
     }
 
   if (ABI_64_P (info->output_bfd))