* elf-bfd.h (_bfd_elf_maybe_strip_eh_frame_hdr): New prototype.
authorJakub Jelinek <jakub@redhat.com>
Sat, 15 Dec 2001 08:54:13 +0000 (08:54 +0000)
committerJakub Jelinek <jakub@redhat.com>
Sat, 15 Dec 2001 08:54:13 +0000 (08:54 +0000)
* elf-eh-frame.c (struct eh_frame_hdr_info): Add strip.
(_bfd_elf_discard_section_eh_frame): Don't create .eh_frame_hdr
sec_info here.  Free ehbuf.
(_bfd_elf_discard_section_eh_frame_hdr): Don't size the section
if hdr_info->strip.
(_bfd_elf_maybe_strip_eh_frame_hdr): New.
* elflink.h (size_dynamic_sections): Call it.

bfd/ChangeLog
bfd/elf-bfd.h
bfd/elf-eh-frame.c
bfd/elflink.h

index 81e491306e545fe2f6df99ce3984f6031cc8a364..e3cc39f05d25f60589c8e46c8a172957bcc091aa 100644 (file)
@@ -1,3 +1,14 @@
+2001-12-15  Jakub Jelinek  <jakub@redhat.com>
+
+       * elf-bfd.h (_bfd_elf_maybe_strip_eh_frame_hdr): New prototype.
+       * elf-eh-frame.c (struct eh_frame_hdr_info): Add strip.
+       (_bfd_elf_discard_section_eh_frame): Don't create .eh_frame_hdr
+       sec_info here.  Free ehbuf.
+       (_bfd_elf_discard_section_eh_frame_hdr): Don't size the section
+       if hdr_info->strip.
+       (_bfd_elf_maybe_strip_eh_frame_hdr): New.
+       * elflink.h (size_dynamic_sections): Call it.
+
 2001-12-14  Alan Modra  <amodra@bigpond.net.au>
 
        * elflink.h (elf_bfd_discard_info): Fix segfault when dynobj NULL.
index d1b088a59baa22914157e68acf079245ab34e2f3..0346c8d19c14c205c814fbe3f16003b2d1490d88 100644 (file)
@@ -1296,6 +1296,8 @@ extern boolean _bfd_elf_write_section_eh_frame
   PARAMS ((bfd *, asection *, asection *, bfd_byte *));
 extern boolean _bfd_elf_write_section_eh_frame_hdr
   PARAMS ((bfd *, asection *));
+extern boolean _bfd_elf_maybe_strip_eh_frame_hdr
+  PARAMS ((struct bfd_link_info *));
 
 extern boolean _bfd_elf_link_record_dynamic_symbol
   PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));
index f215fca036bbfcb51237169b2c88d420009f7801..14c690be3db20bdac79f851b4359f84f037b1c2b 100644 (file)
@@ -86,6 +86,7 @@ struct eh_frame_hdr_info
      We build it if we successfully read all .eh_frame input sections
      and recognize them.  */
   boolean table;
+  boolean strip;
 };
 
 static bfd_vma read_unsigned_leb128
@@ -246,7 +247,7 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,
   struct cie_header hdr;
   struct cie cie;
   struct eh_frame_hdr_info *hdr_info;
-  struct eh_frame_sec_info *sec_info;
+  struct eh_frame_sec_info *sec_info = NULL;
   unsigned int leb128_tmp;
   unsigned int cie_usage_count, last_cie_ndx, i, offset, make_relative;
   Elf_Internal_Rela *rel;
@@ -267,23 +268,20 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,
       return false;
     }
 
+  BFD_ASSERT (elf_section_data (ehdrsec)->sec_info_type
+             == ELF_INFO_TYPE_EH_FRAME_HDR);
+  hdr_info = (struct eh_frame_hdr_info *)
+            elf_section_data (ehdrsec)->sec_info;
+
   /* Read the frame unwind information from abfd.  */
 
   ehbuf = (bfd_byte *) bfd_malloc (sec->_raw_size);
-  if (ehbuf == NULL
-      || ! bfd_get_section_contents (abfd, sec, ehbuf, (bfd_vma) 0,
-                                    sec->_raw_size))
-    {
-      if (elf_section_data (ehdrsec)->sec_info_type
-         != ELF_INFO_TYPE_EH_FRAME_HDR)
-       {
-         elf_section_data (ehdrsec)->sec_info
-           = bfd_zmalloc (sizeof (struct eh_frame_hdr_info));
-         elf_section_data (ehdrsec)->sec_info_type
-           = ELF_INFO_TYPE_EH_FRAME_HDR;
-       }
-      return false;
-    }
+  if (ehbuf == NULL)
+    goto free_no_table;
+
+  if (! bfd_get_section_contents (abfd, sec, ehbuf, (bfd_vma) 0,
+                                 sec->_raw_size))
+    goto free_no_table;
 
   if (sec->_raw_size >= 4
       && bfd_get_32 (abfd, ehbuf) == 0
@@ -294,24 +292,10 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,
       return false;
     }
 
-  if (elf_section_data (ehdrsec)->sec_info_type
-      != ELF_INFO_TYPE_EH_FRAME_HDR)
-    {
-      hdr_info = (struct eh_frame_hdr_info *)      
-                bfd_zmalloc (sizeof (struct eh_frame_hdr_info));
-      hdr_info->table = true;
-      elf_section_data (ehdrsec)->sec_info = hdr_info;
-      elf_section_data (ehdrsec)->sec_info_type
-       = ELF_INFO_TYPE_EH_FRAME_HDR;
-    }
-  else
-    hdr_info = (struct eh_frame_hdr_info *)
-              elf_section_data (ehdrsec)->sec_info;
-
   /* If .eh_frame section size doesn't fit into int, we cannot handle
      it (it would need to use 64-bit .eh_frame format anyway).  */
   if (sec->_raw_size != (unsigned int) sec->_raw_size)
-    return false;
+    goto free_no_table;
 
   ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS]
              == ELFCLASS64) ? 8 : 4;
@@ -650,9 +634,12 @@ _bfd_elf_discard_section_eh_frame (abfd, info, sec, ehdrsec,
   if (sec->_cooked_size == 0)
     sec->flags |= SEC_EXCLUDE;
 
+  free (ehbuf);
   return new_size != sec->_raw_size;
 
 free_no_table:
+  if (ehbuf)
+    free (ehbuf);
   if (sec_info)
     free (sec_info);
   hdr_info->table = false;
@@ -686,6 +673,8 @@ _bfd_elf_discard_section_eh_frame_hdr (abfd, info, sec)
 
   hdr_info = (struct eh_frame_hdr_info *)
             elf_section_data (sec)->sec_info;
+  if (hdr_info->strip)
+    return false;
   sec->_cooked_size = EH_FRAME_HDR_SIZE;
   if (hdr_info->table)
     sec->_cooked_size += 4 + hdr_info->fde_count * 8;
@@ -696,6 +685,52 @@ _bfd_elf_discard_section_eh_frame_hdr (abfd, info, sec)
   return true;
 }
 
+/* This function is called from size_dynamic_sections.
+   It needs to decide whether .eh_frame_hdr should be output or not,
+   because later on it is too late for calling _bfd_strip_section_from_output,
+   since dynamic symbol table has been sized.  */
+
+boolean
+_bfd_elf_maybe_strip_eh_frame_hdr (info)
+     struct bfd_link_info *info;
+{
+  asection *sec, *o;
+  bfd *abfd;
+  struct eh_frame_hdr_info *hdr_info;
+
+  sec = bfd_get_section_by_name (elf_hash_table (info)->dynobj, ".eh_frame_hdr");
+  if (sec == NULL)
+    return true;
+
+  hdr_info
+    = bfd_zmalloc (sizeof (struct eh_frame_hdr_info));
+  if (hdr_info == NULL)
+    return false;
+
+  elf_section_data (sec)->sec_info = hdr_info;
+  elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_EH_FRAME_HDR;
+
+  abfd = NULL;
+  if (info->eh_frame_hdr)
+    for (abfd = info->input_bfds; abfd != NULL; abfd = abfd->link_next)
+      {
+       /* Count only sections which have at least a single CIE or FDE.
+          There cannot be any CIE or FDE <= 8 bytes.  */
+       o = bfd_get_section_by_name (abfd, ".eh_frame");
+       if (o && o->_raw_size > 8)
+         break;
+      }
+
+  if (abfd == NULL)
+    {
+      _bfd_strip_section_from_output (info, sec);
+      hdr_info->strip = true;
+    }
+  else
+    hdr_info->table = true;
+  return true;
+}
+
 /* Adjust an address in the .eh_frame section.  Given OFFSET within
    SEC, this returns the new offset in the adjusted .eh_frame section,
    or -1 if the address refers to a CIE/FDE which has been removed
index a5e348d15be596cfd30c00cc5173f8a1badb437b..311774879ae3076ce9c5ff30d6383a5a4bb32fe5 100644 (file)
@@ -3002,6 +3002,9 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
   if (dynobj == NULL)
     return true;
 
+  if (! _bfd_elf_maybe_strip_eh_frame_hdr (info))
+    return false;
+
   if (elf_hash_table (info)->dynamic_sections_created)
     {
       struct elf_info_failed eif;