This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR ld/5526: EH GC testing output_section too early


In patch 3 of the recent EH GC series, I said:

    ... And that in turn means
    that the parsing routines don't know for sure whether a CIE is
    needed or not.  We could get around this by keeping the extended
    CIE information around and leaving the discard routines to merge CIEs,
    but I think it would be better to merge all CIEs upfront.

But it wasn't better after all.  Merging depends on output_sections
(both the EH section's and the personality routine's) and they aren't
set at GC time.  This was usually a silent failure for the EH frame
section itself; you'd need two output .eh_frame sections to notice it.
However, it meant that personality relocations against local symbols
would be rejected by "ld --gc-sections".

This patch therefore takes the other option above: keeping the extended
CIE information around and merging at discard time.  Data-structure-wise:

  - eh_frame_hdr_info has a separate field ("merge_cies") to say whether
    CIEs should be merged.

  - eh_frame_sec_info stores a pointer to the extended CIEs for a given
    input section.  It is null if !hdr_info->merge_cies.  It is freed
    once all CIEs in an input section have been processed by the
    discard routines (i.e. once each CIE has either been removed,
    merged into another, or kept).

  - eh_frame_hdr_info->cies is created on demand (like it used to be)
    and continues to use separately-allocated memory.

  - The extended cie struct has a new "personality.reloc_index" field
    to hold the index of the personality relocation.  The parsing
    routine sets up this field and leaves the merging routine to
    calculate the actual personality value.

  - eh_cie_fde has a separate field ("u.cie.merged") to say whether it has
    been merged.  While it is in the default state of being removed and
    unmerged, "u.cie.u.full_cie" points to the extended CIE information.

Test results:

  - No regressions in the binutils testsuite on arm-eabi, hppa-linux-gnu,
    i686-linux-gnu, mips64-linux-gnu, sh-linux-gnu and x86_64-linux-gnu.

  - i686-linux-gnu and x86_64-linux-gnu libc.sos and stripped libgcj.sos
    are not affected by the patch.

  - No changes to the GCC testresults for i686-pc-linux-gnu,
    x86_64-linux-gnu, mipsisa64-elfoabi and mips64-linux-gnu
    (all default languages).

  - The mipsisa64-elfoabi libstdc++ testsuites are the same with and
    without --gc-sections.

  - Fixes the attached test on i686-linux-gnu and x86_64-linux-gnu.
    Before the patch, the linker would refuse to create an
    .eh_frame_hdr section.

OK to install?

The PR is about both a refusal to create.eh_frame_hdr and a wrong-code bug.
This patch is only for the first, although I suppose it might fix the
second too.  I think the patch is a strict improvement on what we have now,
so I'd like to install it even if it doesn't fix the wrong-code part on
its own.

Sorry for the breakage.

Richard


bfd/
	PR ld/5526
	* elf-bfd.h (eh_cie_fde): Add u.cie.u.full_cie and u.cie.merged
	fields.  Rename u.cie.u.merged to u.cie.u.merged_with.
	(eh_frame_sec_info): Add a cies field.
	(eh_frame_hdr_info): Add a merge_cies field.
	* elf-eh-frame.c (cie): Add a reloc_index member to the personality
	union.
	(_bfd_elf_begin_eh_frame_parsing): Set hdr_info->merge_cies instead
	of hdr_info->cies.
	(_bfd_elf_parse_eh_frame): Remove tmp_cie.  Ccreate an array of
	cie structures in all cases and use it instead of extended_cies.
	If merging, store the cie array in sec_info->cies and point each
	CIE's eh_fde_cie at the associated element.  Do not try to
	calculate the value of the personality routine here; record the
	offset of the relocation instead.  Do not merge CIEs here.
	(_bfd_elf_end_eh_frame_parsing): Do not free hdr_info->cies here...
	(_bfd_elf_discard_section_eh_frame_hdr): ...do it here instead.
	(_bfd_elf_gc_mark_fdes): Mark the original (unmerged) CIE.
	(find_merged_cie): New function.
	(_bfd_elf_gc_mark_fdes): Use it.  Free sec_info->cies.

ld/testsuite/
	PR ld/5526
	* ld-elf/eh6.s, ld-elf/eh6.d: New test.

Index: bfd/elf-bfd.h
===================================================================
--- bfd/elf-bfd.h	2008-01-04 08:58:23.000000000 +0000
+++ bfd/elf-bfd.h	2008-01-04 08:59:54.000000000 +0000
@@ -276,19 +276,20 @@ struct eh_cie_fde
       struct eh_cie_fde *next_for_section;
     } fde;
     struct {
-      /* In general, equivalent CIEs are grouped together, with one CIE
-	 representing all the others in a group.
+      /* CIEs have three states:
 
-	 If REMOVED == 0, this CIE is the group representative, and
-	 U.SEC points to the .eh_frame section that contains the CIE.
+	 - REMOVED && !MERGED: Slated for removal because we haven't yet
+	   proven that an FDE needs it.  FULL_CIE, if nonnull, points to
+	   more detailed information about the CIE.
 
-	 If REMOVED == 1, this CIE is the group representative if
-	 U.MERGED is a self pointer.  Otherwise, following U.MERGED
-	 brings us "closer" to the CIE's group representative;
-	 if U.MERGED is not the group representative, then
-	 U.MERGED->U.MERGED is.  */
+	 - REMOVED && MERGED: We have merged this CIE with MERGED_WITH,
+	   which may not belong to the same input section.
+
+	 - !REMOVED: We have decided to keep this CIE.  SEC is the
+	   .eh_frame input section that contains the CIE.  */
       union {
- 	struct eh_cie_fde *merged;
+	struct cie *full_cie;
+ 	struct eh_cie_fde *merged_with;
  	asection *sec;
       } u;
 
@@ -296,8 +297,7 @@ struct eh_cie_fde
       unsigned int gc_mark : 1;
 
       /* True if we have decided to turn an absolute LSDA encoding into
-	 a PC-relative one.  It is the group representative's setting
-	 that matters.  */
+	 a PC-relative one.  */
       unsigned int make_lsda_relative : 1;
 
       /* True if the CIE contains personality data and if that data
@@ -307,6 +307,9 @@ struct eh_cie_fde
       /* True if we need to add an 'R' (FDE encoding) entry to the
 	 CIE's augmentation data.  */
       unsigned int add_fde_encoding : 1;
+
+      /* True if we have merged this CIE with another.  */
+      unsigned int merged : 1;
     } cie;
   } u;
   unsigned int reloc_index;
@@ -341,6 +344,7 @@ struct eh_cie_fde
 struct eh_frame_sec_info
 {
   unsigned int count;
+  struct cie *cies;
   struct eh_cie_fde entry[1];
 };
 
@@ -358,6 +362,8 @@ struct eh_frame_hdr_info
   asection *hdr_sec;
   unsigned int fde_count, array_count;
   struct eh_frame_array_ent *array;
+  /* TRUE if we should try to merge CIEs between input sections.  */
+  bfd_boolean merge_cies;
   /* TRUE if all .eh_frames have been parsd.  */
   bfd_boolean parsed_eh_frames;
   /* TRUE if .eh_frame_hdr should contain the sorted search table.
Index: bfd/elf-eh-frame.c
===================================================================
--- bfd/elf-eh-frame.c	2008-01-04 08:58:23.000000000 +0000
+++ bfd/elf-eh-frame.c	2008-01-04 08:59:54.000000000 +0000
@@ -42,6 +42,7 @@ struct cie
   union {
     struct elf_link_hash_entry *h;
     bfd_vma val;
+    unsigned int reloc_index;
   } personality;
   asection *output_sec;
   struct eh_cie_fde *cie_inf;
@@ -431,8 +432,7 @@ _bfd_elf_begin_eh_frame_parsing (struct 
   struct eh_frame_hdr_info *hdr_info;
 
   hdr_info = &elf_hash_table (info)->eh_info;
-  if (!hdr_info->parsed_eh_frames && !info->relocatable)
-    hdr_info->cies = htab_try_create (1, cie_hash, cie_eq, free);
+  hdr_info->merge_cies = !info->relocatable;
 }
 
 /* Try to parse .eh_frame section SEC, which belongs to ABFD.  Store the
@@ -453,13 +453,8 @@ #define REQUIRE(COND)					\
   bfd_byte *last_fde;
   struct eh_cie_fde *this_inf;
   unsigned int hdr_length, hdr_id;
-  struct extended_cie
-    {
-      struct cie *cie;
-      struct eh_cie_fde *local_cie;
-    } *ecies = NULL, *ecie;
-  unsigned int ecie_count;
-  struct cie *cie, *local_cies = NULL, tmp_cie;
+  unsigned int cie_count;
+  struct cie *cie, *local_cies = NULL;
   struct elf_link_hash_table *htab;
   struct eh_frame_hdr_info *hdr_info;
   struct eh_frame_sec_info *sec_info = NULL;
@@ -538,16 +533,9 @@ #define REQUIRE(COND)					\
 			  + (num_entries - 1) * sizeof (struct eh_cie_fde));
   REQUIRE (sec_info);
 
-  ecies = bfd_zmalloc (num_cies * sizeof (*ecies));
-  REQUIRE (ecies);
-
-  /* If we're not merging CIE entries (such as for a relocatable link),
-     we need to have a "struct cie" for each CIE in this section.  */
-  if (hdr_info->cies == NULL)
-    {
-      local_cies = bfd_zmalloc (num_cies * sizeof (*local_cies));
-      REQUIRE (local_cies);
-    }
+  /* We need to have a "struct cie" for each CIE in this section.  */
+  local_cies = bfd_zmalloc (num_cies * sizeof (*local_cies));
+  REQUIRE (local_cies);
 
 #define ENSURE_NO_RELOCS(buf)				\
   REQUIRE (!(cookie->rel < cookie->relend		\
@@ -568,7 +556,7 @@ #define GET_RELOC(buf)					\
    ? cookie->rel : NULL)
 
   buf = ehbuf;
-  ecie_count = 0;
+  cie_count = 0;
   gc_mark_hook = get_elf_backend_data (abfd)->gc_mark_hook;
   while ((bfd_size_type) (buf - ehbuf) != sec->size)
     {
@@ -612,16 +600,9 @@ #define GET_RELOC(buf)					\
 	  /* CIE  */
 	  this_inf->cie = 1;
 
-	  /* If we're merging CIEs, construct the struct cie in TMP_CIE;
-	     we'll enter it into the global pool later.  Otherwise point
-	     CIE to one of the section-local cie structures.  */
-	  if (local_cies)
-	    cie = local_cies + ecie_count;
-	  else
-	    {
-	      cie = &tmp_cie;
-	      memset (cie, 0, sizeof (*cie));
-	    }
+	  /* Point CIE to one of the section-local cie structures.  */
+	  cie = local_cies + cie_count++;
+
 	  cie->cie_inf = this_inf;
 	  cie->length = hdr_length;
 	  cie->output_sec = sec->output_section;
@@ -697,64 +678,14 @@ #define GET_RELOC(buf)					\
 			}
 		      ENSURE_NO_RELOCS (buf);
 		      /* Ensure we have a reloc here.  */
-		      if (GET_RELOC (buf) != NULL)
-			{
-			  unsigned long r_symndx;
-
-#ifdef BFD64
-			  if (elf_elfheader (abfd)->e_ident[EI_CLASS]
-			      == ELFCLASS64)
-			    r_symndx = ELF64_R_SYM (cookie->rel->r_info);
-			  else
-#endif
-			    r_symndx = ELF32_R_SYM (cookie->rel->r_info);
-			  if (r_symndx >= cookie->locsymcount
-			      || ELF_ST_BIND (cookie->locsyms[r_symndx]
-					      .st_info) != STB_LOCAL)
-			    {
-			      struct elf_link_hash_entry *h;
-
-			      r_symndx -= cookie->extsymoff;
-			      h = cookie->sym_hashes[r_symndx];
-
-			      while (h->root.type == bfd_link_hash_indirect
-				     || h->root.type == bfd_link_hash_warning)
-				h = (struct elf_link_hash_entry *)
-				    h->root.u.i.link;
-
-			      cie->personality.h = h;
-			    }
-			  else
-			    {
-			      Elf_Internal_Sym *sym;
-			      asection *sym_sec;
-			      bfd_vma val;
-
-			      sym = &cookie->locsyms[r_symndx];
-			      sym_sec = (bfd_section_from_elf_index
-					 (abfd, sym->st_shndx));
-			      if (sym_sec != NULL)
-				{
-				  if (sym_sec->kept_section != NULL)
-				    sym_sec = sym_sec->kept_section;
-				  if (sym_sec->output_section != NULL)
-				    {
-				      val = (sym->st_value
-					     + sym_sec->output_offset
-					     + sym_sec->output_section->vma);
-				      cie->personality.val = val;
-				      cie->local_personality = 1;
-				    }
-				}
-			    }
-
-			  /* Cope with MIPS-style composite relocations.  */
-			  do
-			    cookie->rel++;
-			  while (GET_RELOC (buf) != NULL);
-			}
+		      REQUIRE (GET_RELOC (buf));
+		      cie->personality.reloc_index
+			= cookie->rel - cookie->rels;
+		      /* Cope with MIPS-style composite relocations.  */
+		      do
+			cookie->rel++;
+		      while (GET_RELOC (buf) != NULL);
 		      REQUIRE (skip_bytes (&buf, end, per_width));
-		      REQUIRE (cie->local_personality || cie->personality.h);
 		    }
 		    break;
 		  default:
@@ -807,6 +738,8 @@ #define GET_RELOC(buf)					\
 	  buf += initial_insn_length;
 	  ENSURE_NO_RELOCS (buf);
 
+	  if (hdr_info->merge_cies)
+	    this_inf->u.cie.u.full_cie = cie;
 	  this_inf->u.cie.per_encoding_relative
 	    = (cie->per_encoding & 0x70) == DW_EH_PE_pcrel;
 	}
@@ -816,18 +749,17 @@ #define GET_RELOC(buf)					\
 
 	  /* Find the corresponding CIE.  */
 	  unsigned int cie_offset = this_inf->offset + 4 - hdr_id;
-	  for (ecie = ecies; ecie < ecies + ecie_count; ++ecie)
-	    if (cie_offset == ecie->local_cie->offset)
+	  for (cie = local_cies; cie < local_cies + cie_count; cie++)
+	    if (cie_offset == cie->cie_inf->offset)
 	      break;
 
 	  /* Ensure this FDE references one of the CIEs in this input
 	     section.  */
-	  REQUIRE (ecie != ecies + ecie_count);
-	  cie = ecie->cie;
-	  this_inf->u.fde.cie_inf = ecie->local_cie;
-	  this_inf->make_relative = ecie->local_cie->make_relative;
+	  REQUIRE (cie != local_cies + cie_count);
+	  this_inf->u.fde.cie_inf = cie->cie_inf;
+	  this_inf->make_relative = cie->cie_inf->make_relative;
 	  this_inf->add_augmentation_size
-	    = ecie->local_cie->add_augmentation_size;
+	    = cie->cie_inf->add_augmentation_size;
 
 	  ENSURE_NO_RELOCS (buf);
 	  REQUIRE (GET_RELOC (buf));
@@ -915,37 +847,18 @@ #define GET_RELOC(buf)					\
       this_inf->removed = 1;
       this_inf->fde_encoding = cie->fde_encoding;
       this_inf->lsda_encoding = cie->lsda_encoding;
-      if (this_inf->cie)
-	{
-	  /* We have now finished constructing the struct cie.  */
-	  if (hdr_info->cies != NULL)
-	    {
-	      /* See if we can merge this CIE with an earlier one.  */
-	      void **loc;
-
-	      cie_compute_hash (cie);
-	      loc = htab_find_slot_with_hash (hdr_info->cies, cie,
-					      cie->hash, INSERT);
-	      REQUIRE (loc);
-	      if (*loc == HTAB_EMPTY_ENTRY)
-		{
-		  *loc = malloc (sizeof (struct cie));
-		  REQUIRE (*loc);
-		  memcpy (*loc, cie, sizeof (struct cie));
-		}
-	      cie = (struct cie *) *loc;
-	    }
-	  this_inf->u.cie.u.merged = cie->cie_inf;
-	  ecies[ecie_count].cie = cie;
-	  ecies[ecie_count++].local_cie = this_inf;
-	}
       sec_info->count++;
     }
   BFD_ASSERT (sec_info->count == num_entries);
-  BFD_ASSERT (ecie_count == num_cies);
+  BFD_ASSERT (cie_count == num_cies);
 
   elf_section_data (sec)->sec_info = sec_info;
   sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME;
+  if (hdr_info->merge_cies)
+    {
+      sec_info->cies = local_cies;
+      local_cies = NULL;
+    }
   goto success;
 
  free_no_table:
@@ -958,8 +871,6 @@ #define GET_RELOC(buf)					\
  success:
   if (ehbuf)
     free (ehbuf);
-  if (ecies)
-    free (ecies);
   if (local_cies)
     free (local_cies);
 #undef REQUIRE
@@ -973,11 +884,6 @@ _bfd_elf_end_eh_frame_parsing (struct bf
   struct eh_frame_hdr_info *hdr_info;
 
   hdr_info = &elf_hash_table (info)->eh_info;
-  if (hdr_info->cies != NULL)
-    {
-      htab_delete (hdr_info->cies);
-      hdr_info->cies = NULL;
-    }
   hdr_info->parsed_eh_frames = TRUE;
 }
 
@@ -1009,7 +915,7 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i
 		       asection *eh_frame, elf_gc_mark_hook_fn gc_mark_hook,
 		       struct elf_reloc_cookie *cookie)
 {
-  struct eh_cie_fde *fde, *cie, *merged;
+  struct eh_cie_fde *fde, *cie;
 
   for (fde = elf_fde_list (sec); fde; fde = fde->u.fde.next_for_section)
     {
@@ -1019,10 +925,9 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i
       /* At this stage, all cie_inf fields point to local CIEs, so we
 	 can use the same cookie to refer to them.  */
       cie = fde->u.fde.cie_inf;
-      merged = cie->u.cie.u.merged;
-      if (!merged->u.cie.gc_mark)
+      if (!cie->u.cie.gc_mark)
 	{
-	  merged->u.cie.gc_mark = 1;
+	  cie->u.cie.gc_mark = 1;
 	  if (!mark_entry (info, eh_frame, cie, gc_mark_hook, cookie))
 	    return FALSE;
 	}
@@ -1030,6 +935,126 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i
   return TRUE;
 }
 
+/* Input section SEC of ABFD is an .eh_frame section that contains the
+   CIE described by CIE_INF.  Return a version of CIE_INF that is going
+   to be kept in the output, adding CIE_INF to the output if necessary.
+
+   HDR_INFO is the .eh_frame_hdr information and COOKIE describes the
+   relocations in REL.  */
+
+static struct eh_cie_fde *
+find_merged_cie (bfd *abfd, asection *sec,
+		 struct eh_frame_hdr_info *hdr_info,
+		 struct elf_reloc_cookie *cookie,
+		 struct eh_cie_fde *cie_inf)
+{
+  unsigned long r_symndx;
+  struct cie *cie, *new_cie;
+  Elf_Internal_Rela *rel;
+  void **loc;
+
+  /* Use CIE_INF if we have already decided to keep it.  */
+  if (!cie_inf->removed)
+    return cie_inf;
+
+  /* If we have merged CIE_INF with another CIE, use that CIE instead.  */
+  if (cie_inf->u.cie.merged)
+    return cie_inf->u.cie.u.merged_with;
+
+  cie = cie_inf->u.cie.u.full_cie;
+
+  /* Assume we will need to keep CIE_INF.  */
+  cie_inf->removed = 0;
+  cie_inf->u.cie.u.sec = sec;
+
+  /* If we are not merging CIEs, use CIE_INF.  */
+  if (cie == NULL)
+    return cie_inf;
+
+  if (cie->per_encoding != DW_EH_PE_omit)
+    {
+      /* Work out the address of personality routine, either as an absolute
+	 value or as a symbol.  */
+      rel = cookie->rels + cie->personality.reloc_index;
+      memset (&cie->personality, 0, sizeof (cie->personality));
+#ifdef BFD64
+      if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64)
+	r_symndx = ELF64_R_SYM (rel->r_info);
+      else
+#endif
+	r_symndx = ELF32_R_SYM (rel->r_info);
+      if (r_symndx >= cookie->locsymcount
+	  || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL)
+	{
+	  struct elf_link_hash_entry *h;
+
+	  r_symndx -= cookie->extsymoff;
+	  h = cookie->sym_hashes[r_symndx];
+
+	  while (h->root.type == bfd_link_hash_indirect
+		 || h->root.type == bfd_link_hash_warning)
+	    h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
+	  cie->personality.h = h;
+	}
+      else
+	{
+	  Elf_Internal_Sym *sym;
+	  asection *sym_sec;
+
+	  sym = &cookie->locsyms[r_symndx];
+	  sym_sec = bfd_section_from_elf_index (abfd, sym->st_shndx);
+	  if (sym_sec == NULL)
+	    return cie_inf;
+
+	  if (sym_sec->kept_section != NULL)
+	    sym_sec = sym_sec->kept_section;
+	  if (sym_sec->output_section == NULL)
+	    return cie_inf;
+
+	  cie->local_personality = 1;
+	  cie->personality.val = (sym->st_value
+				  + sym_sec->output_offset
+				  + sym_sec->output_section->vma);
+	}
+    }
+
+  /* See if we can merge this CIE with an earlier one.  */
+  cie->output_sec = sec->output_section;
+  cie_compute_hash (cie);
+  if (hdr_info->cies == NULL)
+    {
+      hdr_info->cies = htab_try_create (1, cie_hash, cie_eq, free);
+      if (hdr_info->cies == NULL)
+	return cie_inf;
+    }
+  loc = htab_find_slot_with_hash (hdr_info->cies, cie, cie->hash, INSERT);
+  if (loc == NULL)
+    return cie_inf;
+
+  new_cie = (struct cie *) *loc;
+  if (new_cie == NULL)
+    {
+      /* Keep CIE_INF and record it in the hash table.  */
+      new_cie = malloc (sizeof (struct cie));
+      if (new_cie == NULL)
+	return cie_inf;
+
+      memcpy (new_cie, cie, sizeof (struct cie));
+      *loc = new_cie;
+    }
+  else
+    {
+      /* Merge CIE_INF with NEW_CIE->CIE_INF.  */
+      cie_inf->removed = 1;
+      cie_inf->u.cie.merged = 1;
+      cie_inf->u.cie.u.merged_with = new_cie->cie_inf;
+      if (cie_inf->u.cie.make_lsda_relative)
+	new_cie->cie_inf->u.cie.make_lsda_relative = 1;
+    }
+  return new_cie->cie_inf;
+}
+
 /* This function is called for each input file before the .eh_frame
    section is relocated.  It discards duplicate CIEs and FDEs for discarded
    functions.  The function returns TRUE iff any entries have been
@@ -1041,7 +1066,7 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i
     bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *),
     struct elf_reloc_cookie *cookie)
 {
-  struct eh_cie_fde *ent, *cie, *merged;
+  struct eh_cie_fde *ent;
   struct eh_frame_sec_info *sec_info;
   struct eh_frame_hdr_info *hdr_info;
   unsigned int ptr_size, offset;
@@ -1075,31 +1100,17 @@ _bfd_elf_gc_mark_fdes (struct bfd_link_i
 	      }
 	    ent->removed = 0;
 	    hdr_info->fde_count++;
-
-	    cie = ent->u.fde.cie_inf;
-	    if (cie->removed)
-	      {
-		merged = cie->u.cie.u.merged;
-		if (!merged->removed)
-		  /* We have decided to keep the group representative.  */
-		  ent->u.fde.cie_inf = merged;
-		else if (merged->u.cie.u.merged != merged)
-		  /* We didn't keep the original group representative,
-		     but we did keep an alternative.  */
-		  ent->u.fde.cie_inf = merged->u.cie.u.merged;
-		else
-		  {
-		    /* Make the local CIE represent the merged group.  */
-		    merged->u.cie.u.merged = cie;
-		    cie->removed = 0;
-		    cie->u.cie.u.sec = sec;
-		    cie->u.cie.make_lsda_relative
-		      = merged->u.cie.make_lsda_relative;
-		  }
-	      }
+	    ent->u.fde.cie_inf = find_merged_cie (abfd, sec, hdr_info, cookie,
+						  ent->u.fde.cie_inf);
 	  }
       }
 
+  if (sec_info->cies)
+    {
+      free (sec_info->cies);
+      sec_info->cies = NULL;
+    }
+
   ptr_size = (get_elf_backend_data (sec->owner)
 	      ->elf_backend_eh_frame_address_size (sec->owner, sec));
   offset = 0;
@@ -1129,6 +1140,12 @@ _bfd_elf_discard_section_eh_frame_hdr (b
   htab = elf_hash_table (info);
   hdr_info = &htab->eh_info;
 
+  if (hdr_info->cies != NULL)
+    {
+      htab_delete (hdr_info->cies);
+      hdr_info->cies = NULL;
+    }
+
   sec = hdr_info->hdr_sec;
   if (sec == NULL)
     return FALSE;
Index: ld/testsuite/ld-elf/eh6.s
===================================================================
--- /dev/null	2008-01-02 12:46:41.552097000 +0000
+++ ld/testsuite/ld-elf/eh6.s	2008-01-04 09:09:49.000000000 +0000
@@ -0,0 +1,17 @@
+	.section .text.foo, "ax", @progbits
+	.globl	foo
+	.type	foo, @function
+foo:
+	.cfi_startproc simple
+	.cfi_personality 0x80, indirect_ptr
+	ret
+	.cfi_endproc
+	.size	foo, . - foo
+
+	.section .data.rel.ro, "a", @progbits
+indirect_ptr:
+	.long my_personality_v0
+
+	.globl my_personality_v0
+my_personality_v0:
+	.long 0
Index: ld/testsuite/ld-elf/eh6.d
===================================================================
--- /dev/null	2008-01-02 12:46:41.552097000 +0000
+++ ld/testsuite/ld-elf/eh6.d	2008-01-04 09:09:47.000000000 +0000
@@ -0,0 +1,17 @@
+#source: eh6.s
+#ld: --gc-sections -shared
+#readelf: -wf
+#target: x86_64-*-linux-gnu i?86-*-linux-gnu
+
+The section .eh_frame contains:
+
+00000000 0000001[4c] 00000000 CIE
+  Version:               1
+  Augmentation:          "zPR"
+  Code alignment factor: 1
+  Data alignment factor: .*
+  Return address column: .*
+  Augmentation data:     80 .* 1b
+
+  DW_CFA_nop
+#pass


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]