bfd/
[deliverable/binutils-gdb.git] / bfd / elf-eh-frame.c
index 8ec34ab0caba22bdd57ba821c55dd579b3b0ccdf..832a99192deb6a0d172837a1804e116b32c0c3f2 100644 (file)
@@ -1243,10 +1243,30 @@ _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
   if (hdr_info->table)
     sec->size += 4 + hdr_info->fde_count * 8;
 
-  elf_tdata (abfd)->eh_frame_hdr = sec;
+  elf_eh_frame_hdr (abfd) = sec;
   return TRUE;
 }
 
+/* Return true if there is at least one non-empty .eh_frame section in
+   input files.  Can only be called after ld has mapped input to
+   output sections, and before sections are stripped.  */
+bfd_boolean
+_bfd_elf_eh_frame_present (struct bfd_link_info *info)
+{
+  asection *eh = bfd_get_section_by_name (info->output_bfd, ".eh_frame");
+
+  if (eh == NULL)
+    return FALSE;
+
+  /* Count only sections which have at least a single CIE or FDE.
+     There cannot be any CIE or FDE <= 8 bytes.  */
+  for (eh = eh->map_head.s; eh != NULL; eh = eh->map_head.s)
+    if (eh->size > 8)
+      return TRUE;
+
+  return FALSE;
+}
+
 /* This function is called from size_dynamic_sections.
    It needs to decide whether .eh_frame_hdr should be output or not,
    because when the dynamic symbol table has been sized it is too late
@@ -1255,8 +1275,6 @@ _bfd_elf_discard_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
 bfd_boolean
 _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
 {
-  asection *o;
-  bfd *abfd;
   struct elf_link_hash_table *htab;
   struct eh_frame_hdr_info *hdr_info;
 
@@ -1265,24 +1283,9 @@ _bfd_elf_maybe_strip_eh_frame_hdr (struct bfd_link_info *info)
   if (hdr_info->hdr_sec == NULL)
     return TRUE;
 
-  if (bfd_is_abs_section (hdr_info->hdr_sec->output_section))
-    {
-      hdr_info->hdr_sec = NULL;
-      return TRUE;
-    }
-
-  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->size > 8 && !bfd_is_abs_section (o->output_section))
-         break;
-      }
-
-  if (abfd == NULL)
+  if (bfd_is_abs_section (hdr_info->hdr_sec->output_section)
+      || !info->eh_frame_hdr
+      || !_bfd_elf_eh_frame_present (info))
     {
       hdr_info->hdr_sec->flags |= SEC_EXCLUDE;
       hdr_info->hdr_sec = NULL;
@@ -1767,74 +1770,81 @@ _bfd_elf_write_section_eh_frame_hdr (bfd *abfd, struct bfd_link_info *info)
   struct elf_link_hash_table *htab;
   struct eh_frame_hdr_info *hdr_info;
   asection *sec;
-  bfd_byte *contents;
-  asection *eh_frame_sec;
-  bfd_size_type size;
-  bfd_boolean retval;
-  bfd_vma encoded_eh_frame;
+  bfd_boolean retval = TRUE;
 
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
   sec = hdr_info->hdr_sec;
-  if (sec == NULL)
-    return TRUE;
 
-  size = EH_FRAME_HDR_SIZE;
-  if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
-    size += 4 + hdr_info->fde_count * 8;
-  contents = (bfd_byte *) bfd_malloc (size);
-  if (contents == NULL)
-    return FALSE;
-
-  eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
-  if (eh_frame_sec == NULL)
+  if (info->eh_frame_hdr && sec != NULL)
     {
-      free (contents);
-      return FALSE;
-    }
+      bfd_byte *contents;
+      asection *eh_frame_sec;
+      bfd_size_type size;
+      bfd_vma encoded_eh_frame;
+
+      size = EH_FRAME_HDR_SIZE;
+      if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
+       size += 4 + hdr_info->fde_count * 8;
+      contents = (bfd_byte *) bfd_malloc (size);
+      if (contents == NULL)
+       return FALSE;
 
-  memset (contents, 0, EH_FRAME_HDR_SIZE);
-  contents[0] = 1;                             /* Version.  */
-  contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address
-    (abfd, info, eh_frame_sec, 0, sec, 4,
-     &encoded_eh_frame);                       /* .eh_frame offset.  */
+      eh_frame_sec = bfd_get_section_by_name (abfd, ".eh_frame");
+      if (eh_frame_sec == NULL)
+       {
+         free (contents);
+         return FALSE;
+       }
 
-  if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
-    {
-      contents[2] = DW_EH_PE_udata4;           /* FDE count encoding.  */
-      contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; /* Search table enc.  */
-    }
-  else
-    {
-      contents[2] = DW_EH_PE_omit;
-      contents[3] = DW_EH_PE_omit;
-    }
-  bfd_put_32 (abfd, encoded_eh_frame, contents + 4);
+      memset (contents, 0, EH_FRAME_HDR_SIZE);
+      /* Version.  */
+      contents[0] = 1;
+      /* .eh_frame offset.  */
+      contents[1] = get_elf_backend_data (abfd)->elf_backend_encode_eh_address
+       (abfd, info, eh_frame_sec, 0, sec, 4, &encoded_eh_frame);
 
-  if (contents[2] != DW_EH_PE_omit)
-    {
-      unsigned int i;
+      if (hdr_info->array && hdr_info->array_count == hdr_info->fde_count)
+       {
+         /* FDE count encoding.  */
+         contents[2] = DW_EH_PE_udata4;
+         /* Search table encoding.  */
+         contents[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
+       }
+      else
+       {
+         contents[2] = DW_EH_PE_omit;
+         contents[3] = DW_EH_PE_omit;
+       }
+      bfd_put_32 (abfd, encoded_eh_frame, contents + 4);
 
-      bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE);
-      qsort (hdr_info->array, hdr_info->fde_count, sizeof (*hdr_info->array),
-            vma_compare);
-      for (i = 0; i < hdr_info->fde_count; i++)
+      if (contents[2] != DW_EH_PE_omit)
        {
-         bfd_put_32 (abfd,
-                     hdr_info->array[i].initial_loc
-                     - sec->output_section->vma,
-                     contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
-         bfd_put_32 (abfd,
-                     hdr_info->array[i].fde - sec->output_section->vma,
-                     contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
+         unsigned int i;
+
+         bfd_put_32 (abfd, hdr_info->fde_count, contents + EH_FRAME_HDR_SIZE);
+         qsort (hdr_info->array, hdr_info->fde_count,
+                sizeof (*hdr_info->array), vma_compare);
+         for (i = 0; i < hdr_info->fde_count; i++)
+           {
+             bfd_put_32 (abfd,
+                         hdr_info->array[i].initial_loc
+                         - sec->output_section->vma,
+                         contents + EH_FRAME_HDR_SIZE + i * 8 + 4);
+             bfd_put_32 (abfd,
+                         hdr_info->array[i].fde - sec->output_section->vma,
+                         contents + EH_FRAME_HDR_SIZE + i * 8 + 8);
+           }
        }
-    }
 
-  /* FIXME: octets_per_byte.  */
-  retval = bfd_set_section_contents (abfd, sec->output_section,
-                                    contents, (file_ptr) sec->output_offset,
-                                    sec->size);
-  free (contents);
+      /* FIXME: octets_per_byte.  */
+      retval = bfd_set_section_contents (abfd, sec->output_section, contents,
+                                        (file_ptr) sec->output_offset,
+                                        sec->size);
+      free (contents);
+    }
+  if (hdr_info->array != NULL)
+    free (hdr_info->array);
   return retval;
 }
 
This page took 0.02593 seconds and 4 git commands to generate.