or1k: Add the l.adrp insn and supporting relocations
[deliverable/binutils-gdb.git] / bfd / elf-properties.c
index bfb106edc92d1f80035f40ac32e419a9f495ee98..861db73170b8b0ef815025c9def67f503a9c93e1 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF program property support.
-   Copyright (C) 2017 Free Software Foundation, Inc.
+   Copyright (C) 2017-2018 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
@@ -62,7 +62,7 @@ _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz)
   p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p));
   if (p == NULL)
     {
-      _bfd_error_handler (_("%B: out of memory in _bfd_elf_get_property"),
+      _bfd_error_handler (_("%pB: out of memory in _bfd_elf_get_property"),
                          abfd);
       _exit (EXIT_FAILURE);
     }
@@ -88,7 +88,7 @@ _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note)
     {
 bad_size:
       _bfd_error_handler
-       (_("warning: %B: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"),
+       (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"),
         abfd, note->type, note->descsz);
       return FALSE;
     }
@@ -109,7 +109,7 @@ bad_size:
       if (datasz > (size_t) (ptr_end - ptr))
        {
          _bfd_error_handler
-           (_("warning: %B: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"),
+           (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"),
             abfd, note->type, type, datasz);
          /* Clear all properties.  */
          elf_properties (abfd) = NULL;
@@ -148,7 +148,7 @@ bad_size:
              if (datasz != align_size)
                {
                  _bfd_error_handler
-                   (_("warning: %B: corrupt stack size: 0x%x"),
+                   (_("warning: %pB: corrupt stack size: 0x%x"),
                     abfd, datasz);
                  /* Clear all properties.  */
                  elf_properties (abfd) = NULL;
@@ -166,7 +166,7 @@ bad_size:
              if (datasz != 0)
                {
                  _bfd_error_handler
-                   (_("warning: %B: corrupt no copy on protected size: 0x%x"),
+                   (_("warning: %pB: corrupt no copy on protected size: 0x%x"),
                     abfd, datasz);
                  /* Clear all properties.  */
                  elf_properties (abfd) = NULL;
@@ -183,7 +183,7 @@ bad_size:
        }
 
       _bfd_error_handler
-       (_("warning: %B: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"),
+       (_("warning: %pB: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"),
         abfd, note->type, type);
 
 next:
@@ -304,6 +304,102 @@ elf_merge_gnu_property_list (struct bfd_link_info *info, bfd *abfd,
       }
 }
 
+/* Get GNU property section size.  */
+
+static bfd_size_type
+elf_get_gnu_property_section_size (elf_property_list *list,
+                                  unsigned int align_size)
+{
+  bfd_size_type size;
+  unsigned int descsz;
+
+  /* Compute the output section size.  */
+  descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+  descsz = (descsz + 3) & -(unsigned int) 4;
+  size = descsz;
+  for (; list != NULL; list = list->next)
+    {
+      /* There are 4 byte type + 4 byte datasz for each property.  */
+      unsigned int datasz;
+      if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE)
+       datasz = align_size;
+      else
+       datasz = list->property.pr_datasz;
+      size += 4 + 4 + datasz;
+      /* Align each property.  */
+      size = (size + (align_size - 1)) & ~(align_size - 1);
+    }
+
+  return size;
+}
+
+/* Write GNU properties.  */
+
+static void
+elf_write_gnu_properties (bfd *abfd, bfd_byte *contents,
+                         elf_property_list *list, unsigned int size,
+                         unsigned int align_size)
+{
+  unsigned int descsz;
+  unsigned int datasz;
+  Elf_External_Note *e_note;
+
+  e_note = (Elf_External_Note *) contents;
+  descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
+  descsz = (descsz + 3) & -(unsigned int) 4;
+  bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz);
+  bfd_h_put_32 (abfd, size - descsz, &e_note->descsz);
+  bfd_h_put_32 (abfd, NT_GNU_PROPERTY_TYPE_0, &e_note->type);
+  memcpy (e_note->name, "GNU", sizeof "GNU");
+
+  size = descsz;
+  for (; list != NULL; list = list->next)
+    {
+      /* There are 4 byte type + 4 byte datasz for each property.  */
+      if (list->property.pr_type == GNU_PROPERTY_STACK_SIZE)
+       datasz = align_size;
+      else
+       datasz = list->property.pr_datasz;
+      bfd_h_put_32 (abfd, list->property.pr_type, contents + size);
+      bfd_h_put_32 (abfd, datasz, contents + size + 4);
+      size += 4 + 4;
+
+      /* Write out property value.  */
+      switch (list->property.pr_kind)
+       {
+       case property_number:
+         switch (datasz)
+           {
+           default:
+             /* Never should happen.  */
+             abort ();
+
+           case 0:
+             break;
+
+           case 4:
+             bfd_h_put_32 (abfd, list->property.u.number,
+                           contents + size);
+             break;
+
+           case 8:
+             bfd_h_put_64 (abfd, list->property.u.number,
+                           contents + size);
+             break;
+           }
+         break;
+
+       default:
+         /* Never should happen.  */
+         abort ();
+       }
+      size += datasz;
+
+      /* Align each property.  */
+      size = (size + (align_size - 1)) & ~ (align_size - 1);
+    }
+}
+
 /* Set up GNU properties.  Return the first relocatable ELF input with
    GNU properties if found.  Otherwise, return NULL.  */
 
@@ -328,11 +424,15 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
        has_properties = TRUE;
 
        /* Ignore GNU properties from ELF objects with different machine
-          code or class.  */
+          code or class.  Also skip objects without a GNU_PROPERTY note
+          section.  */
        if ((elf_machine_code
             == get_elf_backend_data (abfd)->elf_machine_code)
            && (elfclass
-               == get_elf_backend_data (abfd)->s->elfclass))
+               == get_elf_backend_data (abfd)->s->elfclass)
+           && bfd_get_section_by_name (abfd,
+                                       NOTE_GNU_PROPERTY_SECTION_NAME) != NULL
+           )
          {
            /* Keep .note.gnu.property section in FIRST_PBFD.  */
            first_pbfd = abfd;
@@ -374,10 +474,11 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
 
        if (list != NULL)
          {
-           /* Discard .note.gnu.property section in the rest inputs.  */
+           /* Discard the .note.gnu.property section in this bfd.  */
            sec = bfd_get_section_by_name (abfd,
                                           NOTE_GNU_PROPERTY_SECTION_NAME);
-           sec->output_section = bfd_abs_section_ptr;
+           if (sec != NULL)
+             sec->output_section = bfd_abs_section_ptr;
          }
       }
 
@@ -385,14 +486,13 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
      always sorted by type even if input GNU properties aren't sorted.  */
   if (first_pbfd != NULL)
     {
-      unsigned int size;
-      unsigned int descsz;
+      bfd_size_type size;
       bfd_byte *contents;
-      Elf_External_Note *e_note;
-      unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
+      unsigned int align_size = elfclass == ELFCLASS64 ? 8 : 4;
 
       sec = bfd_get_section_by_name (first_pbfd,
                                     NOTE_GNU_PROPERTY_SECTION_NAME);
+      BFD_ASSERT (sec != NULL);
 
       /* Update stack size in .note.gnu.property with -z stack-size=N
         if N > 0.  */
@@ -420,76 +520,28 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
          return NULL;
        }
 
-      /* Compute the section size.  */
-      descsz = offsetof (Elf_External_Note, name[sizeof "GNU"]);
-      descsz = (descsz + 3) & -(unsigned int) 4;
-      size = descsz;
-      for (list = elf_properties (first_pbfd);
-          list != NULL;
-          list = list->next)
+      /* Fix up GNU properties.  */
+      if (bed->fixup_gnu_properties)
+       bed->fixup_gnu_properties (info, &elf_properties (first_pbfd));
+
+      if (elf_properties (first_pbfd) == NULL)
        {
-         /* There are 4 byte type + 4 byte datasz for each property.  */
-         size += 4 + 4 + list->property.pr_datasz;
-         /* Align each property.  */
-         size = (size + (align_size - 1)) & ~(align_size - 1);
+         /* Discard .note.gnu.property section if all properties have
+            been removed.  */
+         sec->output_section = bfd_abs_section_ptr;
+         return NULL;
        }
 
+      /* Compute the section size.  */
+      list = elf_properties (first_pbfd);
+      size = elf_get_gnu_property_section_size (list, align_size);
+
       /* Update .note.gnu.property section now.  */
       sec->size = size;
       contents = (bfd_byte *) bfd_zalloc (first_pbfd, size);
 
-      e_note = (Elf_External_Note *) contents;
-      bfd_h_put_32 (first_pbfd, sizeof "GNU", &e_note->namesz);
-      bfd_h_put_32 (first_pbfd, size - descsz, &e_note->descsz);
-      bfd_h_put_32 (first_pbfd, NT_GNU_PROPERTY_TYPE_0, &e_note->type);
-      memcpy (e_note->name, "GNU", sizeof "GNU");
-
-      size = descsz;
-      for (list = elf_properties (first_pbfd);
-          list != NULL;
-          list = list->next)
-       {
-         /* There are 4 byte type + 4 byte datasz for each property.  */
-         bfd_h_put_32 (first_pbfd, list->property.pr_type,
-                       contents + size);
-         bfd_h_put_32 (first_pbfd, list->property.pr_datasz,
-                       contents + size + 4);
-         size += 4 + 4;
-
-         /* Write out property value.  */
-         switch (list->property.pr_kind)
-           {
-           case property_number:
-             switch (list->property.pr_datasz)
-               {
-               default:
-                 /* Never should happen.  */
-                 abort ();
-
-               case 0:
-                 break;
-
-               case 4:
-                 bfd_h_put_32 (first_pbfd, list->property.u.number,
-                               contents + size);
-                 break;
-
-               case 8:
-                 bfd_h_put_64 (first_pbfd, list->property.u.number,
-                               contents + size);
-                 break;
-               }
-             break;
-
-           default:
-             /* Never should happen.  */
-             abort ();
-           }
-         size += list->property.pr_datasz;
-
-         /* Align each property.  */
-         size = (size + (align_size - 1)) & ~ (align_size - 1);
-       }
+      elf_write_gnu_properties (first_pbfd, contents, list, size,
+                               align_size);
 
       /* Cache the section contents for elf_link_input_bfd.  */
       elf_section_data (sec)->this_hdr.contents = contents;
@@ -502,3 +554,58 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info)
 
   return first_pbfd;
 }
+
+/* Convert GNU property size.  */
+
+bfd_size_type
+_bfd_elf_convert_gnu_property_size (bfd *ibfd, bfd *obfd)
+{
+  unsigned int align_size;
+  const struct elf_backend_data *bed;
+  elf_property_list *list = elf_properties (ibfd);
+
+  bed = get_elf_backend_data (obfd);
+  align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4;
+
+  /* Get the output .note.gnu.property section size.  */
+  return elf_get_gnu_property_section_size (list, align_size);
+}
+
+/* Convert GNU properties.  */
+
+bfd_boolean
+_bfd_elf_convert_gnu_properties (bfd *ibfd, asection *isec,
+                                bfd *obfd, bfd_byte **ptr,
+                                bfd_size_type *ptr_size)
+{
+  unsigned int size;
+  bfd_byte *contents;
+  unsigned int align_shift;
+  const struct elf_backend_data *bed;
+  elf_property_list *list = elf_properties (ibfd);
+
+  bed = get_elf_backend_data (obfd);
+  align_shift = bed->s->elfclass == ELFCLASS64 ? 3 : 2;
+
+  /* Get the output .note.gnu.property section size.  */
+  size = bfd_get_section_size (isec->output_section);
+
+  /* Update the output .note.gnu.property section alignment.  */
+  bfd_set_section_alignment (obfd, isec->output_section, align_shift);
+
+  if (size > bfd_get_section_size (isec))
+    {
+      contents = (bfd_byte *) bfd_malloc (size);
+      free (*ptr);
+      *ptr = contents;
+    }
+  else
+    contents = *ptr;
+
+  *ptr_size = size;
+
+  /* Generate the output .note.gnu.property section.  */
+  elf_write_gnu_properties (ibfd, contents, list, size, 1 << align_shift);
+
+  return TRUE;
+}
This page took 0.043435 seconds and 4 git commands to generate.