ehdr_start twiddles
authorAlan Modra <amodra@gmail.com>
Fri, 24 Aug 2018 08:07:53 +0000 (17:37 +0930)
committerAlan Modra <amodra@gmail.com>
Fri, 24 Aug 2018 08:55:22 +0000 (18:25 +0930)
We force __ehdr_start to defined in before_allocation, then restore
the type and a union after dynamic symbols have been allocated.
The union contains a number of structs, all starting with a "next"
pointer, and various fields depending on the symbol type.  The old
code restored the entire union, but it isn't necessary to restore the
"next" pointer, and in fact it could be wrong if __ehdr_start happened
to be last on the list and some symbols were added before restoring.

* emultempl/elf32.em (before_allocation): Don't restore
__ehdr_start u.*.next pointer.

ld/ChangeLog
ld/emultempl/elf32.em

index 4b33f72eff50fb9fe7f95b340771cab8db04112b..c2d47fdceaa82259d0093abdd3cf4916e82a10d6 100644 (file)
@@ -1,3 +1,8 @@
+2018-08-24  Alan Modra  <amodra@gmail.com>
+
+       * emultempl/elf32.em (before_allocation): Don't restore
+       __ehdr_start u.*.next pointer.
+
 2018-08-23  Alan Modra  <amodra@gmail.com>
 
        PR 23566
index eac4ba795e9f0914aea266f48fcf7dc90356f2fc..ad31a625ef16cd7a8e1f314f1e82722e2f48f9bf 100644 (file)
@@ -1689,12 +1689,11 @@ gld${EMULATION_NAME}_before_allocation (void)
   const char *rpath;
   asection *sinterp;
   bfd *abfd;
-  struct elf_link_hash_entry *ehdr_start = NULL;
-  struct bfd_link_hash_entry ehdr_start_save;
+  struct bfd_link_hash_entry *ehdr_start = NULL;
+  unsigned char ehdr_start_save_type = 0;
+  char ehdr_start_save_u[sizeof ehdr_start->u
+                        - sizeof ehdr_start->u.def.next] = "";
 
-  /* The memset is here only to silence brain-dead compiler warnings
-     that the variable may be used uninitialized.  */
-  memset (&ehdr_start_save, 0, sizeof ehdr_start_save);
   if (is_elf_hash_table (link_info.hash))
     {
       _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
@@ -1725,11 +1724,14 @@ gld${EMULATION_NAME}_before_allocation (void)
                 we most likely will need dynamic relocations for
                 __ehdr_start if we are building a PIE or shared
                 library.  */
-             ehdr_start = h;
-             ehdr_start_save = h->root;
-             h->root.type = bfd_link_hash_defined;
-             h->root.u.def.section = bfd_abs_section_ptr;
-             h->root.u.def.value = 0;
+             ehdr_start = &h->root;
+             ehdr_start_save_type = ehdr_start->type;
+             memcpy (ehdr_start_save_u,
+                     (char *) &ehdr_start->u + sizeof ehdr_start->u.def.next,
+                     sizeof ehdr_start_save_u);
+             ehdr_start->type = bfd_link_hash_defined;
+             ehdr_start->u.def.section = bfd_abs_section_ptr;
+             ehdr_start->u.def.value = 0;
            }
        }
 
@@ -1848,8 +1850,10 @@ ${ELF_INTERPRETER_SET_DEFAULT}
     {
       /* If we twiddled __ehdr_start to defined earlier, put it back
         as it was.  */
-      ehdr_start->root.type = ehdr_start_save.type;
-      ehdr_start->root.u = ehdr_start_save.u;
+      ehdr_start->type = ehdr_start_save_type;
+      memcpy ((char *) &ehdr_start->u + sizeof ehdr_start->u.def.next,
+             ehdr_start_save_u,
+             sizeof ehdr_start_save_u);
     }
 }