This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
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