Collect .openbsd.syscalls sections into a new PT_OPENBSD_SYSCALLS segment.
authorkettenis <kettenis@openbsd.org>
Thu, 7 Dec 2023 21:57:34 +0000 (21:57 +0000)
committerkettenis <kettenis@openbsd.org>
Thu, 7 Dec 2023 21:57:34 +0000 (21:57 +0000)
This will be used soon to pin system calls to designated call sites.

ok deraadt@

gnu/usr.bin/binutils-2.17/bfd/elf.c
gnu/usr.bin/binutils-2.17/binutils/readelf.c
gnu/usr.bin/binutils-2.17/include/elf/common.h
gnu/usr.bin/binutils-2.17/ld/ldgram.y

index 01d3b34..b23e3a6 100644 (file)
@@ -1105,6 +1105,7 @@ get_segment_type (unsigned int p_type)
     case PT_OPENBSD_NOBTCFI: pt = "OPENBSD_NOBTCFI"; break;
     case PT_OPENBSD_BOOTDATA: pt = "OPENBSD_BOOTDATA"; break;
     case PT_OPENBSD_MUTABLE: pt = "OPENBSD_MUTABLE"; break;
+    case PT_OPENBSD_SYSCALLS: pt = "OPENBSD_SYSCALLS"; break;
     default: pt = NULL; break;
     }
   return pt;
@@ -2654,6 +2655,11 @@ bfd_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index)
     case PT_OPENBSD_MUTABLE:
       return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
                                              "openbsd_mutable");
+
+    case PT_OPENBSD_SYSCALLS:
+      return _bfd_elf_make_section_from_phdr (abfd, hdr, index,
+                                             "openbsd_syscalls");
+
     default:
       /* Check for any processor-specific program segment types.  */
       bed = get_elf_backend_data (abfd);
@@ -3659,6 +3665,7 @@ map_sections_to_segments (bfd *abfd)
   int tls_count = 0;
   asection *first_tls = NULL;
   asection *dynsec, *eh_frame_hdr, *randomdata, *mutabledata;
+  asection *syscalls;
   bfd_size_type amt;
 
   if (elf_tdata (abfd)->segment_map != NULL)
@@ -4044,6 +4051,24 @@ map_sections_to_segments (bfd *abfd)
       pm = &m->next;
     }
 
+  /* If there is a .openbsd.syscalls section, throw in a PT_OPENBSD_SYSCALLS
+     segment.  */
+  syscalls = bfd_get_section_by_name (abfd, ".openbsd.syscalls");
+  if (syscalls != NULL && (syscalls->flags & SEC_LOAD) == 0)
+    {
+      amt = sizeof (struct elf_segment_map);
+      m = bfd_zalloc (abfd, amt);
+      if (m == NULL)
+       goto error_return;
+      m->next = NULL;
+      m->p_type = PT_OPENBSD_SYSCALLS;
+      m->count = 1;
+      m->sections[0] = syscalls->output_section;
+
+      *pm = m;
+      pm = &m->next;
+    }
+
   if (elf_tdata (abfd)->relro)
     {
       amt = sizeof (struct elf_segment_map);
@@ -4594,6 +4619,12 @@ assign_file_positions_for_segments (bfd *abfd, struct bfd_link_info *link_info)
              else if (p->p_type == PT_NOTE
                  && (flags & SEC_HAS_CONTENTS) != 0)
                p->p_filesz += sec->size;
+             else if (p->p_type == PT_OPENBSD_SYSCALLS)
+               {
+                 sec->filepos = off;
+                 off += sec->size;
+                 p->p_filesz += sec->size;
+               }
 
              /* .tbss is special.  It doesn't contribute to p_memsz of
                 normal segments.  */
@@ -4796,6 +4827,12 @@ get_program_header_size (bfd *abfd)
       ++segs;
     }
 
+  if (bfd_get_section_by_name (abfd, ".openbsd.syscalls") != NULL)
+    {
+      /* We need a PT_OPENBSD_SYSCALLS segment.  */
+      ++segs;
+    }
+
   if (elf_tdata (abfd)->eh_frame_hdr)
     {
       /* We need a PT_GNU_EH_FRAME segment.  */
index 262a0b3..eacb32f 100644 (file)
@@ -2713,6 +2713,8 @@ get_segment_type (unsigned long p_type)
                        return "OPENBSD_MUTABLE";
     case PT_OPENBSD_NOBTCFI:
                        return "OPENBSD_NOBTCFI";
+    case PT_OPENBSD_SYSCALLS:
+                       return "OPENBSD_SYSCALLS";
 
     default:
       if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
index a494372..1fe2ce9 100644 (file)
 #define PT_OPENBSD_NOBTCFI     0x65a3dbe8 /* no branch target CFI */
 #define PT_OPENBSD_BOOTDATA    0x65a41be6 /* Section for boot arguments */
 #define PT_OPENBSD_MUTABLE     0x65a3dbe5 /* Like bss, but not immutable */
+#define PT_OPENBSD_SYSCALLS    0x65a3dbe9 /* System call sites */
 
 /* Program segment permissions, in program header p_flags field.  */
 
index 5ed2a5f..60097ab 100644 (file)
@@ -1101,6 +1101,8 @@ phdr_type:
                            $$ = exp_intop (0x65a41be6);
                          else if (strcmp (s, "PT_OPENBSD_MUTABLE") == 0)
                            $$ = exp_intop (0x65a3dbe5);
+                         else if (strcmp (s, "PT_OPENBSD_SYSCALLS") == 0)
+                           $$ = exp_intop (0x65a3dbe9);
                          else
                            {
                              einfo (_("\