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]

Re: PATCH: PR ld/14105: Always create PLT eh_frame


On Mon, May 21, 2012 at 5:11 PM, Alan Modra <amodra@gmail.com> wrote:
> On Mon, May 21, 2012 at 07:40:26AM -0700, H.J. Lu wrote:
>> My elflink.c change is to remove the redundant CIE above.
>
> Oh, I see. ?I guess I didn't look at the patch in enough detail..
> Perhaps it might be better to implement bfd_get_next_section_by_name?
>
> asection *
> bfd_get_next_section_by_name (bfd *abfd, asection *sec)
> {
> ?struct section_hash_entry *sh;
> ?sh = ((struct section_hash_entry *)
> ? ? ? ?((char *) sec - offsetof (struct section_hash_entry *, section)));
> ?...
> }
>

Does this one look OK?

Thanks.


-- 
H.J.
---
bfd/

2012-05-21  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/14105
	* elf32-i386.c (elf_i386_create_dynamic_sections): Always
	create PLT eh_frame section with SEC_LINKER_CREATED.
	* elf64-x86-64.c (elf_x86_64_create_dynamic_sections): Likewise.

	* elflink.c (bfd_elf_discard_info): Also handle PLT eh_frame
	created by linker.

	* section.c (bfd_get_next_section_by_name): New.
	* bfd-in2.h: Regenerated.

ld/testsuite/

2012-05-21  H.J. Lu  <hongjiu.lu@intel.com>

	PR ld/14105
	* ld-elf/eh4.d: Add PLT eh_frame.

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 7535483..5de86e3 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -1704,6 +1704,8 @@ void bfd_section_list_clear (bfd *);

 asection *bfd_get_section_by_name (bfd *abfd, const char *name);

+asection *bfd_get_next_section_by_name (bfd *abfd, asection *sec);
+
 asection *bfd_get_section_by_name_if
    (bfd *abfd,
     const char *name,
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index dd49486..84299ce 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -1015,13 +1015,15 @@ elf_i386_create_dynamic_sections (bfd *dynobj,
struct bfd_link_info *info)
     return FALSE;

   if (!info->no_ld_generated_unwind_info
-      && bfd_get_section_by_name (dynobj, ".eh_frame") == NULL
+      && htab->plt_eh_frame == NULL
       && htab->elf.splt != NULL)
     {
       flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags;
       htab->plt_eh_frame
-	= bfd_make_section_with_flags (dynobj, ".eh_frame",
-				       flags | SEC_READONLY);
+	= bfd_make_section_anyway_with_flags (dynobj, ".eh_frame",
+					      (flags
+					       | SEC_LINKER_CREATED
+					       | SEC_READONLY));
       if (htab->plt_eh_frame == NULL
 	  || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2))
 	return FALSE;
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 3353560..1f490d4 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -979,15 +979,17 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj,
     abort ();

   if (!info->no_ld_generated_unwind_info
-      && bfd_get_section_by_name (dynobj, ".eh_frame") == NULL
+      && htab->plt_eh_frame == NULL
       && htab->elf.splt != NULL)
     {
       const struct elf_x86_64_backend_data *const abed
 	= get_elf_x86_64_backend_data (dynobj);
       flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags;
       htab->plt_eh_frame
-	= bfd_make_section_with_flags (dynobj, ".eh_frame",
-				       flags | SEC_READONLY);
+	= bfd_make_section_anyway_with_flags (dynobj, ".eh_frame",
+					      (flags
+					       | SEC_LINKER_CREATED
+					       | SEC_READONLY));
       if (htab->plt_eh_frame == NULL
 	  || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3))
 	return FALSE;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 3614575..d834ac2 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -12468,7 +12468,7 @@ bfd_elf_discard_info (bfd *output_bfd, struct
bfd_link_info *info)
   asection *stab, *eh;
   const struct elf_backend_data *bed;
   bfd *abfd;
-  bfd_boolean ret = FALSE;
+  bfd_boolean ret = FALSE, plt_eh_frame_done = FALSE;

   if (info->traditional_format
       || !is_elf_hash_table (info->hash))
@@ -12531,6 +12531,23 @@ bfd_elf_discard_info (bfd *output_bfd, struct
bfd_link_info *info)
 						 &cookie))
 	    ret = TRUE;
 	  fini_reloc_cookie_rels (&cookie, eh);
+
+	  if (!plt_eh_frame_done)
+	    {
+	      /* Also handle PLT eh_frame created by linker.  */
+	      eh = bfd_get_next_section_by_name (abfd, eh);
+	      if (eh != NULL
+		  && init_reloc_cookie_rels (&cookie, info, abfd, eh))
+		{
+		  plt_eh_frame_done = TRUE;
+		  _bfd_elf_parse_eh_frame (abfd, info, eh, &cookie);
+		  if (_bfd_elf_discard_section_eh_frame (abfd, info, eh,
+							 bfd_elf_reloc_symbol_deleted_p,
+							 &cookie))
+		    ret = TRUE;
+		  fini_reloc_cookie_rels (&cookie, eh);
+		}
+	    }
 	}

       if (bed->elf_backend_discard_info != NULL
diff --git a/bfd/section.c b/bfd/section.c
index 3a70ccf..42e5a5c 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -869,6 +869,61 @@ bfd_get_section_by_name (bfd *abfd, const char *name)

 /*
 FUNCTION
+	bfd_get_next_section_by_name
+
+SYNOPSIS
+	asection *bfd_get_next_section_by_name (bfd *abfd, asection *sec);
+
+DESCRIPTION
+	Return the next section attached to the BFD @var{abfd} after
+	secton @var{sec} with the same section name.  It returns NULL
+	if no such section is found.
+*/
+
+asection *
+bfd_get_next_section_by_name (bfd *abfd, asection *sec)
+{
+  struct section_hash_entry *sh;
+  const char *name;
+  unsigned long hash;
+
+  sh = (struct section_hash_entry *)
+    ((char *) sec - offsetof (struct section_hash_entry, section));
+
+  BFD_ASSERT (sh != NULL);
+
+  /* Find the section.  */
+  hash = sh->root.hash;
+  name = sec->name;
+  do
+    {
+      if (&sh->section == sec)
+	break;
+      sh = (struct section_hash_entry *) sh->root.next;
+    }
+  while (sh != NULL
+	 && sh->root.hash == hash
+	 && strcmp (sh->root.string, name) == 0);
+
+  BFD_ASSERT (sh != NULL);
+
+  /* Find the next secton in ABFD with the same name.  */
+  for (sh = (struct section_hash_entry *) sh->root.next;
+       sh != NULL;
+       sh = (struct section_hash_entry *) sh->root.next)
+    if (sh->root.hash == hash
+	&& sec->owner == abfd
+	&& strcmp (sh->root.string, name) == 0)
+      break;
+
+  if (sh != NULL)
+    return &sh->section;
+
+  return NULL;
+}
+
+/*
+FUNCTION
 	bfd_get_section_by_name_if

 SYNOPSIS
diff --git a/ld/testsuite/ld-elf/eh4.d b/ld/testsuite/ld-elf/eh4.d
index b482d03..34ce70e 100644
--- a/ld/testsuite/ld-elf/eh4.d
+++ b/ld/testsuite/ld-elf/eh4.d
@@ -29,6 +29,17 @@ Contents of the .eh_frame section:
   DW_CFA_set_loc: 00000417
   DW_CFA_def_cfa_offset: 80

-00000048 ZERO terminator
+00000048 00000024 0000004c FDE cie=00000000 pc=00000240..00000260
+  DW_CFA_def_cfa_offset: 16
+  DW_CFA_advance_loc: 6 to 00000246
+  DW_CFA_def_cfa_offset: 24
+  DW_CFA_advance_loc: 10 to 00000250
+  DW_CFA_def_cfa_expression \(DW_OP_breg7 \(rsp\): 8; DW_OP_breg16
\(rip\): 0; DW_OP_lit15; DW_OP_and; DW_OP_lit11; DW_OP_ge; DW_OP_lit3;
DW_OP_shl; DW_OP_plus\)
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+  DW_CFA_nop
+
+00000070 ZERO terminator
 #pass


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