This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: PATCH: IA64 unwind section references discarded section
On Fri, Apr 01, 2005 at 03:37:47PM -0800, H. J. Lu wrote:
> On Thu, Mar 31, 2005 at 10:20:27PM -0800, H. J. Lu wrote:
> > This is the same problem as
> >
> > http://sourceware.org/ml/binutils/2004-08/msg00187.html
> > http://sourceware.org/ml/binutils/2004-08/msg00190.html
> >
> > But this time it is icc, which doesn't use gas. I would like to see a
> > linker solution.
> >
> >
>
> This is a linker patch. It creates a fake group section for a
> linkonce text sections and its unwind sections. The fake group
> section is removed before the output file is written.
>
This updated patch works for me.
H.J.
----
bfd/
2005-04-02 H.J. Lu <hongjiu.lu@intel.com>
* elf.c (bfd_elf_set_group_contents): Ignore linker created
group section.
(assign_section_numbers): Remove the linker created group
sections.
* elfxx-ia64.c (elfNN_ia64_object_p): New.
(elf_backend_object_p): Defined.
gas/
2005-04-02 H.J. Lu <hongjiu.lu@intel.com>
* config/tc-ia64.c (start_unwind_section): Undo the change
of 2004-08-18.
(generate_unwind_image, dot_endp): Likewise.
--- binutils/bfd/elf.c.unwind 2005-04-01 17:45:16.000000000 -0800
+++ binutils/bfd/elf.c 2005-04-02 07:55:42.154467729 -0800
@@ -2635,7 +2635,9 @@ bfd_elf_set_group_contents (bfd *abfd, a
struct bfd_link_order *l;
bfd_boolean gas;
- if (elf_section_data (sec)->this_hdr.sh_type != SHT_GROUP
+ /* Ignore linker created group section. See elfNN_ia64_object_p in
+ elfxx-ia64.c. */
+ if (((sec->flags & (SEC_GROUP | SEC_LINKER_CREATED)) != SEC_GROUP)
|| *failedptr)
return;
@@ -2729,29 +2731,55 @@ static bfd_boolean
assign_section_numbers (bfd *abfd)
{
struct elf_obj_tdata *t = elf_tdata (abfd);
- asection *sec;
+ asection *sec, **group_secp;
unsigned int section_number, secn;
Elf_Internal_Shdr **i_shdrp;
bfd_size_type amt;
struct bfd_elf_section_data *d;
+ bfd_boolean found;
section_number = 1;
_bfd_elf_strtab_clear_all_refs (elf_shstrtab (abfd));
/* Put SHT_GROUP sections first. */
+ group_secp = &abfd->sections;
+ found = FALSE;
for (sec = abfd->sections; sec; sec = sec->next)
{
d = elf_section_data (sec);
if (d->this_hdr.sh_type == SHT_GROUP)
{
+ if (sec->flags & SEC_LINKER_CREATED)
+ {
+ /* Find the first linker screated SHT_GROUP section. */
+ found = TRUE;
+ }
if (section_number == SHN_LORESERVE)
section_number += SHN_HIRESERVE + 1 - SHN_LORESERVE;
d->this_idx = section_number++;
}
+
+ if (!found)
+ group_secp = &(*group_secp)->next;
}
+ /* Remove the linker created SHT_GROUP sections. */
+ if (found)
+ do
+ {
+ if (((*group_secp)->flags & (SEC_GROUP | SEC_LINKER_CREATED))
+ == (SEC_GROUP | SEC_LINKER_CREATED))
+ {
+ bfd_section_list_remove (abfd, group_secp);
+ abfd->section_count--;
+ }
+ else
+ group_secp = &(*group_secp)->next;
+ }
+ while (*group_secp);
+
for (sec = abfd->sections; sec; sec = sec->next)
{
d = elf_section_data (sec);
--- binutils/bfd/elfxx-ia64.c.unwind 2005-03-21 13:13:37.000000000 -0800
+++ binutils/bfd/elfxx-ia64.c 2005-04-02 07:51:04.764390400 -0800
@@ -4886,6 +4886,118 @@ static struct bfd_elf_special_section co
};
static bfd_boolean
+elfNN_ia64_object_p (bfd *abfd)
+{
+ asection *sec;
+ unsigned int num_group = 0;
+
+ if (abfd->flags & DYNAMIC)
+ return TRUE;
+
+ /* Count number of .gnu.linkonce.t.* sections which aren't in a
+ section group. */
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ if (elf_sec_group (sec) == NULL
+ && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE | SEC_GROUP))
+ == (SEC_LINK_ONCE | SEC_CODE))
+ && strncmp (sec->name, ".gnu.linkonce.t.", 16) == 0)
+ num_group++;
+ }
+
+ if (num_group)
+ {
+ asection *group, *unwi, *unw;
+ flagword flags;
+ const char *name;
+ char *unwi_name, *unw_name;
+ bfd_size_type amt;
+ Elf_Internal_Shdr shdr;
+
+ /* Fake SHT_GROUP section header. */
+ memset (&shdr, 0, sizeof (shdr));
+ shdr.sh_type = SHT_GROUP;
+
+ /* Flags for fake group section. */
+ flags = (SEC_LINKER_CREATED | SEC_GROUP | SEC_LINK_ONCE
+ | SEC_EXCLUDE);
+
+ /* We add a fake section group for each linkonce text section and
+ its unwind sections. */
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ if (elf_sec_group (sec) == NULL
+ && ((sec->flags & (SEC_LINK_ONCE | SEC_CODE | SEC_GROUP))
+ == (SEC_LINK_ONCE | SEC_CODE))
+ && strncmp (sec->name, ".gnu.linkonce.t.", 16) == 0)
+ {
+ name = sec->name + 16;
+
+ amt = strlen (name) + sizeof (".gnu.linkonce.ia64unwi.");
+ unwi_name = bfd_alloc (abfd, amt);
+ if (!unwi_name)
+ return FALSE;
+
+ strcpy (stpcpy (unwi_name, ".gnu.linkonce.ia64unwi."),
+ name);
+ unwi = bfd_get_section_by_name (abfd, unwi_name);
+
+ amt = strlen (name) + sizeof (".gnu.linkonce.ia64unw.");
+ unw_name = bfd_alloc (abfd, amt);
+ if (!unw_name)
+ return FALSE;
+
+ strcpy (stpcpy (unw_name, ".gnu.linkonce.ia64unw."),
+ name);
+ unw = bfd_get_section_by_name (abfd, unw_name);
+
+ /* We need to create a fake group section for it and its
+ unwind sections. */
+ group = bfd_make_section_anyway (abfd, name);
+ if (group == NULL
+ || ! bfd_set_section_flags (abfd, group, flags))
+ return FALSE;
+
+ elf_next_in_group (group) = sec;
+
+ elf_group_name (sec) = name;
+ elf_next_in_group (sec) = sec;
+ elf_sec_group (sec) = group;
+
+ if (unwi)
+ {
+ elf_group_name (unwi) = name;
+ elf_next_in_group (unwi) = sec;
+ elf_next_in_group (sec) = unwi;
+ elf_sec_group (unwi) = group;
+ }
+
+ if (unw)
+ {
+ elf_group_name (unw) = name;
+ if (unwi)
+ {
+ elf_next_in_group (unw)
+ = elf_next_in_group (unwi);
+ elf_next_in_group (unwi) = unw;
+ }
+ else
+ {
+ elf_next_in_group (unw) = sec;
+ elf_next_in_group (sec) = unw;
+ }
+ elf_sec_group (unw) = group;
+ }
+
+ shdr.bfd_section = group;
+ elf_section_data (group)->this_hdr = shdr;
+ }
+ }
+ }
+ return TRUE;
+}
+
+static bfd_boolean
elfNN_ia64_hpux_vec (const bfd_target *vec)
{
extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
@@ -4968,6 +5080,9 @@ elfNN_hpux_backend_symbol_processing (bf
#define bfd_elfNN_bfd_relax_section \
elfNN_ia64_relax_section
+#define elf_backend_object_p \
+ elfNN_ia64_object_p
+
/* Stuff for the BFD linker: */
#define bfd_elfNN_bfd_link_hash_table_create \
elfNN_ia64_hash_table_create
--- binutils/gas/config/tc-ia64.c.unwind 2005-04-01 17:45:20.000000000 -0800
+++ binutils/gas/config/tc-ia64.c 2005-04-01 17:53:16.000000000 -0800
@@ -3460,7 +3460,7 @@ static char *special_linkonce_name[] =
};
static void
-start_unwind_section (const segT text_seg, int sec_index, int linkonce_empty)
+start_unwind_section (const segT text_seg, int sec_index)
{
/*
Use a slightly ugly scheme to derive the unwind section names from
@@ -3522,8 +3522,6 @@ start_unwind_section (const segT text_se
prefix = special_linkonce_name [sec_index - SPECIAL_SECTION_UNWIND];
suffix += sizeof (".gnu.linkonce.t.") - 1;
}
- else if (linkonce_empty)
- return;
prefix_len = strlen (prefix);
suffix_len = strlen (suffix);
@@ -3611,7 +3609,7 @@ generate_unwind_image (const segT text_s
expressionS exp;
bfd_reloc_code_real_type reloc;
- start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 0);
+ start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO);
/* Make sure the section has 4 byte alignment for ILP32 and
8 byte alignment for LP64. */
@@ -3652,8 +3650,6 @@ generate_unwind_image (const segT text_s
unwind.personality_routine = 0;
}
}
- else
- start_unwind_section (text_seg, SPECIAL_SECTION_UNWIND_INFO, 1);
free_saved_prologue_counts ();
unwind.list = unwind.tail = unwind.current_entry = NULL;
@@ -4426,7 +4422,7 @@ dot_endp (dummy)
subseg_set (md.last_text_seg, 0);
proc_end = expr_build_dot ();
- start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 0);
+ start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND);
/* Make sure that section has 4 byte alignment for ILP32 and
8 byte alignment for LP64. */
@@ -4466,9 +4462,6 @@ dot_endp (dummy)
bytes_per_address);
}
- else
- start_unwind_section (saved_seg, SPECIAL_SECTION_UNWIND, 1);
-
subseg_set (saved_seg, saved_subseg);
if (unwind.proc_start)