PATCH: Support mixing COMDAT and linkonce
H. J. Lu
hjl@lucon.org
Tue May 18 01:06:00 GMT 2004
On Mon, May 17, 2004 at 02:24:23PM -0700, H. J. Lu wrote:
> On Sat, May 15, 2004 at 11:09:47AM +0930, Alan Modra wrote:
> > On Fri, May 14, 2004 at 02:07:37PM -0700, H. J. Lu wrote:
> > > When there are mixed COMDAT and linkonce inputs, linker doesn't handle
> > > them gracefully:
> >
> > Ewww. Should we even try? I understand that such a patch might be
> > useful while gcc is emitting both comdat and linkonce, but once you've
> > completed the change to comdat it shouldn't be necessary. Also, I'm not
> > really happy with where you have added this code. At least, it is the
> > wrong place to be discarding duplicate sections. That ought to happen
> > in ldlang.c:section_already_linked.
> >
>
> This patch implements it.
>
>
Here is an update. I should skip checking members of section groups
for already linked section.
I think there may be a bug in ldlang.c:section_already_linked. We
check section names for linkonce sections. But for group sections,
section names are meaningless. Compilers/assemblers don't have to
use group signature for section name. Shouldn't we check for group
signatures instead?
H.J.
-------------- next part --------------
bfd/
2004-05-17 H.J. Lu <hongjiu.lu@intel.com>
* aout-adobe.c (aout_32_bfd_match_symbols_in_sections): Defined.
* aout-target.h (MY_bfd_match_symbols_in_sections): Likewise.
* aout-tic30.c (MY_bfd_match_symbols_in_sections): Likewise.
* binary.c (binary_bfd_match_symbols_in_sections): Likewise.
* bout.c (b_out_bfd_match_symbols_in_sections): Likewise.
* coff-alpha.c (_bfd_ecoff_bfd_match_symbols_in_sections): Likewise.
* coff-mips.c (_bfd_ecoff_bfd_match_symbols_in_sections): Likewise.
* coffcode.h (coff_bfd_match_symbols_in_sections): Likewise.
* i386msdos.c (msdos_bfd_match_symbols_in_sections): Likewise.
* i386os9k.c (os9k_bfd_match_symbols_in_sections): Likewise.
* ieee.c (ieee_bfd_match_symbols_in_sections): Likewise.
* ihex.c (ihex_bfd_match_symbols_in_sections): Likewise.
* mach-o.c (bfd_mach_o_bfd_match_symbols_in_sections): Likewise.
* mmo.c (mmo_bfd_discard_group): Likewise.
* nlm-target.h (nlm_bfd_match_symbols_in_sections): Likewise.
* oasys.c (oasys_bfd_match_symbols_in_sections): Likewise.
* pef.c (bfd_pef_bfd_match_symbols_in_sections): Likewise.
* ppcboot.c (ppcboot_bfd_match_symbols_in_sections): Likewise.
* som.c (som_bfd_discard_group): Likewise.
* srec.c (srec_bfd_match_symbols_in_sections): Likewise.
* tekhex.c (tekhex_bfd_match_symbols_in_sections): Likewise.
* versados.c (versados_bfd_match_symbols_in_sections): Likewise.
* vms.c (vms_bfd_match_symbols_in_sections): Likewise.
* coff-target.h (_bfd_xcoff_bfd_match_symbols_in_sections): Likewise.
* xsym.c (bfd_sym_bfd_match_symbols_in_sections): Likewise.
* bfd.c (bfd_match_symbols_in_sections): New.
* coff-rs6000.c (rs6000coff_vec): Add
_bfd_nolink_bfd_match_symbols_in_sections,
(pmac_xcoff_vec): Likewise.
* coff64-rs6000.c (rs6000coff64_vec): Likewise.
(aix5coff64_vec): Likewise.
* elf-bfd.h (bfd_elf_match_symbols_in_sections): New prototype.
(_bfd_elf_setup_group_pointers): Likewise.
* elf.c (_bfd_elf_setup_group_pointers): New function.
(elf_sort_elf_symbol): Likewise.
(elf_sym_name_compare): Likewise.
(bfd_elf_match_symbols_in_sections): Likewise.
* elfcode.h (elf_object_p): Call _bfd_elf_setup_group_pointers.
* elfxx-target.h (bfd_elfNN_bfd_match_symbols_in_sections): Defined.
* libbfd-in.h (_bfd_nolink_bfd_match_symbols_in_sections): Defined/
* section.c (bfd_section): Add group, a pointer to section group.
* section (STD_SECTION): Initialize group to NULL.
* ecoff.c (bfd_debug_section): Likewise.
* targets.c (bfd_target): Add _bfd_match_symbols_in_sections.
(BFD_JUMP_TABLE_LINK): Updated.
* bfd-in2.h: Regenerated.
* libbfd.h: Regenerated.
ld/
2004-05-17 H.J. Lu <hongjiu.lu@intel.com>
* ldlang.c (already_linked_section): New structure.
(try_match_symbols_in_sections): New function.
(section_already_linked): Check if a member of a COMDAT group
matches a .gnu.linkonce section.
--- binutils/bfd/aout-adobe.c.linkonce 2004-04-30 08:25:52.000000000 -0700
+++ binutils/bfd/aout-adobe.c 2004-05-17 13:27:55.000000000 -0700
@@ -519,6 +519,8 @@ aout_adobe_sizeof_headers (ignore_abfd,
#define aout_32_bfd_merge_sections bfd_generic_merge_sections
#define aout_32_bfd_is_group_section bfd_generic_is_group_section
#define aout_32_bfd_discard_group bfd_generic_discard_group
+#define aout_32_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define aout_32_bfd_link_hash_table_create \
_bfd_generic_link_hash_table_create
#define aout_32_bfd_link_hash_table_free \
--- binutils/bfd/aout-target.h.linkonce 2004-04-30 08:25:53.000000000 -0700
+++ binutils/bfd/aout-target.h 2004-05-17 09:41:08.000000000 -0700
@@ -519,6 +519,10 @@ MY_bfd_final_link (abfd, info)
#ifndef MY_bfd_discard_group
#define MY_bfd_discard_group bfd_generic_discard_group
#endif
+#ifndef MY_bfd_match_symbols_in_sections
+#define MY_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
+#endif
#ifndef MY_bfd_reloc_type_lookup
#define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup)
#endif
--- binutils/bfd/aout-tic30.c.linkonce 2004-04-30 08:25:54.000000000 -0700
+++ binutils/bfd/aout-tic30.c 2004-05-17 09:41:32.000000000 -0700
@@ -976,6 +976,10 @@ tic30_aout_set_arch_mach (abfd, arch, ma
#ifndef MY_bfd_discard_group
#define MY_bfd_discard_group bfd_generic_discard_group
#endif
+#ifndef MY_bfd_match_symbols_in_sections
+#define MY_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
+#endif
#ifndef MY_bfd_reloc_type_lookup
#define MY_bfd_reloc_type_lookup tic30_aout_reloc_type_lookup
#endif
--- binutils/bfd/bfd.c.linkonce 2004-05-14 09:00:52.000000000 -0700
+++ binutils/bfd/bfd.c 2004-05-17 09:40:43.000000000 -0700
@@ -1089,6 +1089,9 @@ DESCRIPTION
.#define bfd_discard_group(abfd, sec) \
. BFD_SEND (abfd, _bfd_discard_group, (abfd, sec))
.
+.#define bfd_match_symbols_in_sections(abfd, sec1, sec2) \
+. BFD_SEND (abfd, _bfd_match_symbols_in_sections, (sec1, sec2))
+.
.#define bfd_link_hash_table_create(abfd) \
. BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd))
.
--- binutils/bfd/binary.c.linkonce 2004-04-30 08:26:01.000000000 -0700
+++ binutils/bfd/binary.c 2004-05-17 09:41:47.000000000 -0700
@@ -341,6 +341,8 @@ binary_sizeof_headers (abfd, exec)
#define binary_bfd_merge_sections bfd_generic_merge_sections
#define binary_bfd_is_group_section bfd_generic_is_group_section
#define binary_bfd_discard_group bfd_generic_discard_group
+#define binary_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define binary_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define binary_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define binary_bfd_link_just_syms _bfd_generic_link_just_syms
--- binutils/bfd/bout.c.linkonce 2004-04-30 08:26:02.000000000 -0700
+++ binutils/bfd/bout.c 2004-05-17 13:28:43.000000000 -0700
@@ -1489,6 +1489,8 @@ b_out_bfd_get_relocated_section_contents
#define b_out_bfd_merge_sections bfd_generic_merge_sections
#define b_out_bfd_is_group_section bfd_generic_is_group_section
#define b_out_bfd_discard_group bfd_generic_discard_group
+#define b_out_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define aout_32_get_section_contents_in_window \
_bfd_generic_get_section_contents_in_window
--- binutils/bfd/coff-alpha.c.linkonce 2004-04-30 08:26:04.000000000 -0700
+++ binutils/bfd/coff-alpha.c 2004-05-17 09:41:52.000000000 -0700
@@ -2361,6 +2361,8 @@ static const struct ecoff_backend_data a
#define _bfd_ecoff_bfd_merge_sections bfd_generic_merge_sections
#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
+#define _bfd_ecoff_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
const bfd_target ecoffalpha_little_vec =
{
--- binutils/bfd/coff-mips.c.linkonce 2004-04-30 08:26:06.000000000 -0700
+++ binutils/bfd/coff-mips.c 2004-05-17 09:42:02.000000000 -0700
@@ -1395,6 +1395,8 @@ static const struct ecoff_backend_data m
#define _bfd_ecoff_bfd_is_group_section bfd_generic_is_group_section
#define _bfd_ecoff_bfd_discard_group bfd_generic_discard_group
+#define _bfd_ecoff_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
extern const bfd_target ecoff_big_vec;
--- binutils/bfd/coff-rs6000.c.linkonce 2004-04-30 08:26:10.000000000 -0700
+++ binutils/bfd/coff-rs6000.c 2004-05-17 09:42:06.000000000 -0700
@@ -4198,6 +4198,7 @@ const bfd_target rs6000coff_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_nolink_bfd_match_symbols_in_sections,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -4442,6 +4443,7 @@ const bfd_target pmac_xcoff_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_nolink_bfd_match_symbols_in_sections,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
--- binutils/bfd/coff64-rs6000.c.linkonce 2004-04-30 08:26:13.000000000 -0700
+++ binutils/bfd/coff64-rs6000.c 2004-05-17 09:42:18.000000000 -0700
@@ -2739,6 +2739,7 @@ const bfd_target rs6000coff64_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_nolink_bfd_match_symbols_in_sections,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -2984,6 +2985,7 @@ const bfd_target aix5coff64_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_nolink_bfd_match_symbols_in_sections,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
--- binutils/bfd/coffcode.h.linkonce 2004-05-07 13:21:00.000000000 -0700
+++ binutils/bfd/coffcode.h 2004-05-17 09:42:24.000000000 -0700
@@ -5574,6 +5574,11 @@ static const bfd_coff_backend_data ticof
#define coff_bfd_discard_group bfd_generic_discard_group
#endif
+#ifndef coff_bfd_match_symbols_in_sections
+#define coff_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
+#endif
+
#define CREATE_BIG_COFF_TARGET_VEC(VAR, NAME, EXTRA_O_FLAGS, EXTRA_S_FLAGS, UNDER, ALTERNATIVE, SWAP_TABLE) \
const bfd_target VAR = \
{ \
--- binutils/bfd/ecoff.c.linkonce 2004-04-26 21:11:29.000000000 -0700
+++ binutils/bfd/ecoff.c 2004-05-17 13:30:52.000000000 -0700
@@ -95,8 +95,8 @@ static asection bfd_debug_section =
NULL, NULL, 0, 0, 0,
/* line_filepos, userdata, contents, lineno, lineno_count, */
0, NULL, NULL, NULL, 0,
- /* entsize, comdat, kept_section, moving_line_filepos, */
- 0, NULL, NULL, 0,
+ /* entsize, comdat, group, kept_section, moving_line_filepos, */
+ 0, NULL, NULL, NULL, 0,
/* target_index, used_by_bfd, constructor_chain, owner, */
0, NULL, NULL, NULL,
/* symbol, */
--- binutils/bfd/elf-bfd.h.linkonce 2004-05-11 13:33:49.000000000 -0700
+++ binutils/bfd/elf-bfd.h 2004-05-17 12:32:04.000000000 -0700
@@ -1375,6 +1375,8 @@ extern bfd_boolean bfd_elf_is_group_sect
(bfd *, const struct bfd_section *);
extern bfd_boolean bfd_elf_discard_group
(bfd *, struct bfd_section *);
+extern bfd_boolean bfd_elf_match_symbols_in_sections
+ (struct bfd_section *, struct bfd_section *);
extern void bfd_elf_set_group_contents
(bfd *, asection *, void *);
extern void _bfd_elf_link_just_syms
@@ -1554,6 +1556,9 @@ extern bfd_boolean _bfd_elf_dynamic_symb
extern bfd_boolean _bfd_elf_symbol_refs_local_p
(struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean);
+extern void _bfd_elf_setup_group_pointers
+ (bfd *);
+
extern const bfd_target *bfd_elf32_object_p
(bfd *);
extern const bfd_target *bfd_elf32_core_file_p
--- binutils/bfd/elf.c.linkonce 2004-05-11 13:33:56.000000000 -0700
+++ binutils/bfd/elf.c 2004-05-17 14:14:58.000000000 -0700
@@ -612,6 +612,26 @@ setup_group (bfd *abfd, Elf_Internal_Shd
return TRUE;
}
+void
+_bfd_elf_setup_group_pointers (bfd *abfd)
+{
+ unsigned int i;
+ unsigned int num_group = elf_tdata (abfd)->num_group;
+
+ if (num_group == (unsigned) -1)
+ return;
+
+ for (i = 0; i < num_group; i++)
+ {
+ Elf_Internal_Shdr *shdr = elf_tdata (abfd)->group_sect_ptr[i];
+ Elf_Internal_Group *idx = (Elf_Internal_Group *) shdr->contents;
+ unsigned int n_elt = shdr->sh_size / 4;
+
+ while (--n_elt != 0)
+ (++idx)->shdr->bfd_section->group = shdr->bfd_section;
+ }
+}
+
bfd_boolean
bfd_elf_is_group_section (bfd *abfd ATTRIBUTE_UNUSED, const asection *sec)
{
@@ -7678,3 +7698,240 @@ _bfd_elf_get_synthetic_symtab (bfd *abfd
return n;
}
+
+/* Sort symbol by binding and section. We want to put global
+ symbols sorted by section at the beginning. */
+
+static int
+elf_sort_elf_symbol (const void *arg1, const void *arg2)
+{
+ const Elf_Internal_Sym *s1;
+ const Elf_Internal_Sym *s2;
+
+ /* Make sure local or undefined symbols are at the end. */
+ s1 = (const Elf_Internal_Sym *) arg1;
+ if (s1->st_shndx == SHN_UNDEF
+ || ELF_ST_BIND (s1->st_info) == STB_LOCAL)
+ return 1;
+ s2 = (const Elf_Internal_Sym *) arg2;
+ if (s2->st_shndx == SHN_UNDEF
+ || ELF_ST_BIND (s2->st_info) == STB_LOCAL)
+ return -1;
+
+ /* Grouped by section index. */
+ return s1->st_shndx - s2->st_shndx;
+}
+
+struct elf_symbol
+{
+ Elf_Internal_Sym *sym;
+ const char *name;
+};
+
+static int
+elf_sym_name_compare (const void *arg1, const void *arg2)
+{
+ const struct elf_symbol *s1 = (const struct elf_symbol *) arg1;
+ const struct elf_symbol *s2 = (const struct elf_symbol *) arg2;
+ return strcmp (s1->name, s2->name);
+}
+
+/* Check if 2 sections export the same set of symbols. */
+
+bfd_boolean
+bfd_elf_match_symbols_in_sections (asection *sec1, asection *sec2)
+{
+ bfd *bfd1, *bfd2;
+ const struct elf_backend_data *bed1, *bed2;
+ Elf_Internal_Shdr *hdr1, *hdr2;
+ bfd_size_type symcount1, symcount2;
+ bfd_size_type extsymcount1, extsymcount2;
+ bfd_size_type extsymoff1, extsymoff2;
+ Elf_Internal_Sym *isymbuf1, *isymbuf2;
+ Elf_Internal_Sym *isymstart1 = NULL, *isymstart2 = NULL, *isym;
+ Elf_Internal_Sym *isymend;
+ struct elf_symbol *symp, *symtable1 = NULL, *symtable2 = NULL;
+ bfd_size_type count1, count2, i;
+ int shndx1, shndx2;
+ bfd_boolean result;
+
+ bfd1 = sec1->owner;
+ bfd2 = sec2->owner;
+
+ /* Both sections have to be in ELF. */
+ if (bfd_get_flavour (bfd1) != bfd_target_elf_flavour
+ || bfd_get_flavour (bfd2) != bfd_target_elf_flavour)
+ return FALSE;
+
+ /* One section has to be in a COMDAT group with only one section and
+ the other one has to be a .gnu.linkonce section. */
+ if (!(elf_section_type (sec1) == elf_section_type (sec2)
+ && ((elf_section_flags (sec1) & ~SHF_GROUP)
+ == (elf_section_flags (sec2) & ~SHF_GROUP))
+ && ((sec1->group != NULL
+ && ((sec1->group->flags & (SEC_LINK_ONCE
+ | SEC_LINK_DUPLICATES_DISCARD))
+ == (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD))
+ && elf_next_in_group (sec1) == sec1
+ && sec2->group == NULL
+ && ((sec2->flags & (SEC_LINK_ONCE
+ | SEC_LINK_DUPLICATES_DISCARD))
+ == (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD)))
+ || (sec1->group == NULL
+ && sec2->group != NULL
+ && ((sec2->group->flags & (SEC_LINK_ONCE
+ | SEC_LINK_DUPLICATES_DISCARD))
+ == (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD))
+ && elf_next_in_group (sec2) == sec2
+ && ((sec1->flags & (SEC_LINK_ONCE
+ | SEC_LINK_DUPLICATES_DISCARD))
+ == (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD))))))
+ return FALSE;
+
+ shndx1 = _bfd_elf_section_from_bfd_section (bfd1, sec1);
+ shndx2 = _bfd_elf_section_from_bfd_section (bfd2, sec2);
+ if (shndx1 == -1 || shndx2 == -1)
+ return FALSE;
+
+ bed1 = get_elf_backend_data (bfd1);
+ bed2 = get_elf_backend_data (bfd2);
+ hdr1 = &elf_tdata (bfd1)->symtab_hdr;
+ symcount1 = hdr1->sh_size / bed1->s->sizeof_sym;
+ hdr2 = &elf_tdata (bfd2)->symtab_hdr;
+ symcount2 = hdr2->sh_size / bed2->s->sizeof_sym;
+
+ if (elf_bad_symtab (bfd1))
+ {
+ extsymcount1 = symcount1;
+ extsymoff1 = 0;
+ }
+ else
+ {
+ extsymcount1 = symcount1 - hdr1->sh_info;
+ extsymoff1 = hdr1->sh_info;
+ }
+
+ if (elf_bad_symtab (bfd2))
+ {
+ extsymcount2 = symcount2;
+ extsymoff2 = 0;
+ }
+ else
+ {
+ extsymcount2 = symcount2 - hdr2->sh_info;
+ extsymoff2 = hdr2->sh_info;
+ }
+
+ if (extsymcount1 == 0 || extsymcount2 == 0)
+ return FALSE;
+
+ isymbuf1 = bfd_elf_get_elf_syms (bfd1, hdr1, extsymcount1,
+ extsymoff1, NULL, NULL, NULL);
+ isymbuf2 = bfd_elf_get_elf_syms (bfd2, hdr2, extsymcount2,
+ extsymoff2, NULL, NULL, NULL);
+ if (isymbuf1 == NULL || isymbuf2 == NULL)
+ return FALSE;
+
+ /* Sort symbols by binding and section. Global definitions are at
+ the beginning. */
+ qsort (isymbuf1, extsymcount1, sizeof (Elf_Internal_Sym),
+ elf_sort_elf_symbol);
+ qsort (isymbuf2, extsymcount2, sizeof (Elf_Internal_Sym),
+ elf_sort_elf_symbol);
+
+ /* Count global symbols defined in the section. */
+ count1 = 0;
+ for (isym = isymbuf1, isymend = isym + extsymcount1;
+ isym < isymend; isym++)
+ {
+ if (isym->st_shndx == (unsigned int) shndx1)
+ {
+ if (count1 == 0)
+ isymstart1 = isym;
+ count1++;
+ }
+
+ if (count1 && isym->st_shndx != (unsigned int) shndx1)
+ break;
+ }
+
+ count2 = 0;
+ for (isym = isymbuf2, isymend = isym + extsymcount2;
+ isym < isymend; isym++)
+ {
+ if (isym->st_shndx == (unsigned int) shndx2)
+ {
+ if (count2 == 0)
+ isymstart2 = isym;
+ count2++;
+ }
+
+ if (count2 && isym->st_shndx != (unsigned int) shndx2)
+ break;
+ }
+
+ if (count1 == 0 && count2 == 0)
+ {
+ result = TRUE;
+ goto done;
+ }
+
+ result = FALSE;
+ if (count1 != count2)
+ goto done;
+
+ symtable1 = bfd_malloc (count1 * sizeof (struct elf_symbol));
+ symtable2 = bfd_malloc (count1 * sizeof (struct elf_symbol));
+
+ if (symtable1 == NULL || symtable2 == NULL)
+ goto done;
+
+ symp = symtable1;
+ for (isym = isymstart1, isymend = isym + count1;
+ isym < isymend; isym++)
+ {
+ symp->sym = isym;
+ symp->name = bfd_elf_string_from_elf_section (bfd1,
+ hdr1->sh_link,
+ isym->st_name);
+ symp++;
+ }
+
+ symp = symtable2;
+ for (isym = isymstart2, isymend = isym + count1;
+ isym < isymend; isym++)
+ {
+ symp->sym = isym;
+ symp->name = bfd_elf_string_from_elf_section (bfd2,
+ hdr2->sh_link,
+ isym->st_name);
+ symp++;
+ }
+
+ /* Sort symbol by name. */
+ qsort (symtable1, count1, sizeof (struct elf_symbol),
+ elf_sym_name_compare);
+ qsort (symtable2, count1, sizeof (struct elf_symbol),
+ elf_sym_name_compare);
+
+ for (i = 0; i < count1; i++)
+ /* Two symbols must have the same binding, type and name. */
+ if (symtable1 [i].sym->st_info != symtable2 [i].sym->st_info
+ || symtable1 [i].sym->st_other != symtable2 [i].sym->st_other
+ || strcmp (symtable1 [i].name, symtable2 [i].name) != 0)
+ goto done;
+
+ result = TRUE;
+
+done:
+ if (symtable1)
+ free (symtable1);
+ if (symtable2)
+ free (symtable2);
+ if (isymbuf1)
+ free (isymbuf1);
+ if (isymbuf2)
+ free (isymbuf2);
+
+ return result;
+}
--- binutils/bfd/elfcode.h.linkonce 2004-04-22 08:20:00.000000000 -0700
+++ binutils/bfd/elfcode.h 2004-05-17 12:30:41.000000000 -0700
@@ -742,6 +742,9 @@ elf_object_p (bfd *abfd)
if (shindex == SHN_LORESERVE - 1)
shindex += SHN_HIRESERVE + 1 - SHN_LORESERVE;
}
+
+ /* Set up group pointers. */
+ _bfd_elf_setup_group_pointers (abfd);
}
/* Let the backend double check the format and override global
--- binutils/bfd/elfxx-target.h.linkonce 2004-04-30 08:26:46.000000000 -0700
+++ binutils/bfd/elfxx-target.h 2004-05-17 09:42:45.000000000 -0700
@@ -144,6 +144,11 @@
#define bfd_elfNN_bfd_discard_group bfd_elf_discard_group
#endif
+#ifndef bfd_elfNN_bfd_match_symbols_in_sections
+#define bfd_elfNN_bfd_match_symbols_in_sections \
+ bfd_elf_match_symbols_in_sections
+#endif
+
#ifndef bfd_elfNN_bfd_make_debug_symbol
#define bfd_elfNN_bfd_make_debug_symbol \
((asymbol * (*) (bfd *, void *, unsigned long)) bfd_nullvoidptr)
--- binutils/bfd/i386msdos.c.linkonce 2004-04-30 08:26:47.000000000 -0700
+++ binutils/bfd/i386msdos.c 2004-05-17 09:42:50.000000000 -0700
@@ -178,6 +178,8 @@ msdos_set_section_contents (abfd, sectio
#define msdos_bfd_merge_sections bfd_generic_merge_sections
#define msdos_bfd_is_group_section bfd_generic_is_group_section
#define msdos_bfd_discard_group bfd_generic_discard_group
+#define msdos_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define msdos_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define msdos_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define msdos_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/i386os9k.c.linkonce 2004-04-30 08:26:47.000000000 -0700
+++ binutils/bfd/i386os9k.c 2004-05-17 13:33:11.000000000 -0700
@@ -335,6 +335,8 @@ os9k_sizeof_headers (ignore_abfd, ignore
#define os9k_bfd_merge_sections bfd_generic_merge_sections
#define os9k_bfd_is_group_section bfd_generic_is_group_section
#define os9k_bfd_discard_group bfd_generic_discard_group
+#define os9k_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define os9k_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define os9k_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define os9k_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/ieee.c.linkonce 2004-04-30 08:26:50.000000000 -0700
+++ binutils/bfd/ieee.c 2004-05-17 09:42:58.000000000 -0700
@@ -4039,6 +4039,8 @@ ieee_bfd_debug_info_accumulate (abfd, se
#define ieee_bfd_merge_sections bfd_generic_merge_sections
#define ieee_bfd_is_group_section bfd_generic_is_group_section
#define ieee_bfd_discard_group bfd_generic_discard_group
+#define ieee_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define ieee_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define ieee_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define ieee_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/ihex.c.linkonce 2004-04-30 08:26:51.000000000 -0700
+++ binutils/bfd/ihex.c 2004-05-17 09:43:03.000000000 -0700
@@ -990,6 +990,8 @@ ihex_sizeof_headers (abfd, exec)
#define ihex_bfd_merge_sections bfd_generic_merge_sections
#define ihex_bfd_is_group_section bfd_generic_is_group_section
#define ihex_bfd_discard_group bfd_generic_discard_group
+#define ihex_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define ihex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define ihex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define ihex_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/libbfd-in.h.linkonce 2004-04-30 08:26:52.000000000 -0700
+++ binutils/bfd/libbfd-in.h 2004-05-17 09:43:08.000000000 -0700
@@ -361,6 +361,9 @@ extern bfd_boolean _bfd_generic_set_sect
#define _bfd_nolink_bfd_discard_group \
((bfd_boolean (*) (bfd *, struct bfd_section *)) \
bfd_false)
+#define _bfd_nolink_bfd_match_symbols_in_sections \
+ ((bfd_boolean (*) (struct bfd_section *, struct bfd_section *)) \
+ bfd_false)
#define _bfd_nolink_bfd_link_hash_table_create \
((struct bfd_link_hash_table *(*) (bfd *)) bfd_nullvoidptr)
#define _bfd_nolink_bfd_link_hash_table_free \
--- binutils/bfd/mach-o.c.linkonce 2004-04-30 08:26:56.000000000 -0700
+++ binutils/bfd/mach-o.c 2004-05-17 09:43:35.000000000 -0700
@@ -70,6 +70,8 @@
#define bfd_mach_o_bfd_merge_sections bfd_generic_merge_sections
#define bfd_mach_o_bfd_is_group_section bfd_generic_is_group_section
#define bfd_mach_o_bfd_discard_group bfd_generic_discard_group
+#define bfd_mach_o_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
static bfd_boolean bfd_mach_o_bfd_copy_private_symbol_data
PARAMS ((bfd *, asymbol *, bfd *, asymbol *));
--- binutils/bfd/mmo.c.linkonce 2004-04-30 08:26:59.000000000 -0700
+++ binutils/bfd/mmo.c 2004-05-17 09:43:40.000000000 -0700
@@ -3288,6 +3288,8 @@ mmo_canonicalize_reloc (abfd, section, r
#define mmo_bfd_merge_sections bfd_generic_merge_sections
#define mmo_bfd_is_group_section bfd_generic_is_group_section
#define mmo_bfd_discard_group bfd_generic_discard_group
+#define mmo_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
/* objcopy will be upset if we return -1 from bfd_get_reloc_upper_bound by
using BFD_JUMP_TABLE_RELOCS (_bfd_norelocs) rather than 0. FIXME: Most
--- binutils/bfd/nlm-target.h.linkonce 2004-04-30 08:26:59.000000000 -0700
+++ binutils/bfd/nlm-target.h 2004-05-17 09:43:45.000000000 -0700
@@ -46,6 +46,8 @@ Foundation, Inc., 59 Temple Place - Suit
#define nlm_bfd_merge_sections bfd_generic_merge_sections
#define nlm_bfd_is_group_section bfd_generic_is_group_section
#define nlm_bfd_discard_group bfd_generic_discard_group
+#define nlm_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define nlm_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define nlm_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define nlm_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/oasys.c.linkonce 2004-04-30 08:27:01.000000000 -0700
+++ binutils/bfd/oasys.c 2004-05-17 09:43:49.000000000 -0700
@@ -1508,6 +1508,8 @@ oasys_sizeof_headers (abfd, exec)
#define oasys_bfd_merge_sections bfd_generic_merge_sections
#define oasys_bfd_is_group_section bfd_generic_is_group_section
#define oasys_bfd_discard_group bfd_generic_discard_group
+#define oasys_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define oasys_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define oasys_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define oasys_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/pef.c.linkonce 2004-04-30 08:27:01.000000000 -0700
+++ binutils/bfd/pef.c 2004-05-17 13:33:50.000000000 -0700
@@ -54,6 +54,7 @@
#define bfd_pef_bfd_merge_sections bfd_generic_merge_sections
#define bfd_pef_bfd_is_group_section bfd_generic_is_group_section
#define bfd_pef_bfd_discard_group bfd_generic_discard_group
+#define bfd_pef_bfd_match_symbols_in_sections _bfd_nolink_bfd_match_symbols_in_sections
#define bfd_pef_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define bfd_pef_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define bfd_pef_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/ppcboot.c.linkonce 2004-04-30 08:27:02.000000000 -0700
+++ binutils/bfd/ppcboot.c 2004-05-17 09:44:21.000000000 -0700
@@ -471,6 +471,8 @@ ppcboot_bfd_print_private_bfd_data (abfd
#define ppcboot_bfd_merge_sections bfd_generic_merge_sections
#define ppcboot_bfd_is_group_section bfd_generic_is_group_section
#define ppcboot_bfd_discard_group bfd_generic_discard_group
+#define ppcboot_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define ppcboot_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define ppcboot_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define ppcboot_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/section.c.linkonce 2004-05-17 07:37:17.000000000 -0700
+++ binutils/bfd/section.c 2004-05-17 07:38:59.000000000 -0700
@@ -493,6 +493,10 @@ CODE_FRAGMENT
. {* Optional information about a COMDAT entry; NULL if not COMDAT. *}
. struct bfd_comdat_info *comdat;
.
+. {* Optional information about section group; NULL if it doesn't
+. belongs to any section group. *}
+. struct bfd_section *group;
+.
. {* Points to the kept section if this section is a link-once section,
. and is discarded. *}
. struct bfd_section *kept_section;
@@ -643,8 +647,8 @@ static const asymbol global_syms[] =
/* line_filepos, userdata, contents, lineno, lineno_count, */ \
0, NULL, NULL, NULL, 0, \
\
- /* entsize, comdat, kept_section, moving_line_filepos, */ \
- 0, NULL, NULL, 0, \
+ /* entsize, comdat, group, kept_section, moving_line_filepos, */ \
+ 0, NULL, NULL, NULL, 0, \
\
/* target_index, used_by_bfd, constructor_chain, owner, */ \
0, NULL, NULL, NULL, \
--- binutils/bfd/som.c.linkonce 2004-05-03 09:00:44.000000000 -0700
+++ binutils/bfd/som.c 2004-05-17 09:44:25.000000000 -0700
@@ -6412,6 +6412,8 @@ som_bfd_link_split_section (abfd, sec)
#define som_bfd_merge_sections bfd_generic_merge_sections
#define som_bfd_is_group_section bfd_generic_is_group_section
#define som_bfd_discard_group bfd_generic_discard_group
+#define som_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
const bfd_target som_vec = {
"som", /* name */
--- binutils/bfd/srec.c.linkonce 2004-04-30 08:27:15.000000000 -0700
+++ binutils/bfd/srec.c 2004-05-17 09:44:33.000000000 -0700
@@ -1286,6 +1286,8 @@ srec_print_symbol (abfd, afile, symbol,
#define srec_bfd_merge_sections bfd_generic_merge_sections
#define srec_bfd_is_group_section bfd_generic_is_group_section
#define srec_bfd_discard_group bfd_generic_discard_group
+#define srec_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define srec_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define srec_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define srec_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/targets.c.linkonce 2004-05-14 09:00:50.000000000 -0700
+++ binutils/bfd/targets.c 2004-05-17 09:44:55.000000000 -0700
@@ -407,7 +407,8 @@ BFD_JUMP_TABLE macros.
. NAME##_bfd_gc_sections, \
. NAME##_bfd_merge_sections, \
. NAME##_bfd_is_group_section, \
-. NAME##_bfd_discard_group
+. NAME##_bfd_discard_group, \
+. NAME##_bfd_match_symbols_in_sections \
.
. int (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
. bfd_byte * (*_bfd_get_relocated_section_contents)
@@ -450,6 +451,11 @@ BFD_JUMP_TABLE macros.
. {* Discard members of a group. *}
. bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *);
.
+. {* Return TRUE if need to try if 2 sections export the same set of
+. symbols. *}
+. bfd_boolean (*_bfd_match_symbols_in_sections)
+. (struct bfd_section *, struct bfd_section *);
+.
. {* Routines to handle dynamic symbols and relocs. *}
.#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
. NAME##_get_dynamic_symtab_upper_bound, \
--- binutils/bfd/tekhex.c.linkonce 2004-04-30 08:27:18.000000000 -0700
+++ binutils/bfd/tekhex.c 2004-05-17 09:45:02.000000000 -0700
@@ -1003,6 +1003,8 @@ tekhex_print_symbol (abfd, filep, symbol
#define tekhex_bfd_merge_sections bfd_generic_merge_sections
#define tekhex_bfd_is_group_section bfd_generic_is_group_section
#define tekhex_bfd_discard_group bfd_generic_discard_group
+#define tekhex_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define tekhex_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define tekhex_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define tekhex_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/versados.c.linkonce 2004-04-30 08:27:18.000000000 -0700
+++ binutils/bfd/versados.c 2004-05-17 09:45:10.000000000 -0700
@@ -874,6 +874,8 @@ versados_canonicalize_reloc (abfd, secti
#define versados_bfd_merge_sections bfd_generic_merge_sections
#define versados_bfd_is_group_section bfd_generic_is_group_section
#define versados_bfd_discard_group bfd_generic_discard_group
+#define versados_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define versados_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define versados_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define versados_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/bfd/vms.c.linkonce 2004-04-30 08:27:20.000000000 -0700
+++ binutils/bfd/vms.c 2004-05-17 13:35:00.000000000 -0700
@@ -168,6 +168,8 @@ static bfd_boolean vms_bfd_set_private_f
#define vms_bfd_link_just_syms _bfd_generic_link_just_syms
#define vms_bfd_is_group_section bfd_generic_is_group_section
#define vms_bfd_discard_group bfd_generic_discard_group
+#define vms_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
/*===========================================================================*/
--- binutils/bfd/xcoff-target.h.linkonce 2002-12-04 09:03:10.000000000 -0800
+++ binutils/bfd/xcoff-target.h 2004-05-17 09:45:17.000000000 -0700
@@ -99,6 +99,8 @@ extern int lynx_core_file_failing_signal
#define _bfd_xcoff_bfd_gc_sections coff_bfd_gc_sections
#define _bfd_xcoff_bfd_merge_sections coff_bfd_merge_sections
#define _bfd_xcoff_bfd_discard_group bfd_generic_discard_group
+#define _bfd_xcoff_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define _bfd_xcoff_bfd_link_split_section coff_bfd_link_split_section
/* XCOFF archives do not have anything which corresponds to an
--- binutils/bfd/xsym.c.linkonce 2004-04-30 08:27:22.000000000 -0700
+++ binutils/bfd/xsym.c 2004-05-17 09:45:22.000000000 -0700
@@ -44,6 +44,8 @@
#define bfd_sym_bfd_merge_sections bfd_generic_merge_sections
#define bfd_sym_bfd_is_group_section bfd_generic_is_group_section
#define bfd_sym_bfd_discard_group bfd_generic_discard_group
+#define bfd_sym_bfd_match_symbols_in_sections \
+ _bfd_nolink_bfd_match_symbols_in_sections
#define bfd_sym_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
#define bfd_sym_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
#define bfd_sym_bfd_link_add_symbols _bfd_generic_link_add_symbols
--- binutils/ld/ldlang.c.linkonce 2004-05-14 09:00:52.000000000 -0700
+++ binutils/ld/ldlang.c 2004-05-17 17:47:45.000000000 -0700
@@ -853,6 +853,36 @@ struct already_linked
asection *sec;
};
+struct already_linked_section
+{
+ asection *sec;
+ asection *linked;
+};
+
+static bfd_boolean
+try_match_symbols_in_sections (struct already_linked_hash_entry *h,
+ void *info)
+{
+ struct already_linked *l;
+ struct already_linked_section *s
+ = (struct already_linked_section *) info;
+
+ /* No need to check group section. */
+ if ((s->sec->flags & SEC_GROUP) != 0)
+ return TRUE;
+
+ for (l = h->entry; l != NULL; l = l->next)
+ if ((l->sec->flags & SEC_GROUP) == 0
+ && bfd_match_symbols_in_sections (l->sec->owner,
+ l->sec, s->sec))
+ {
+ s->linked = l->sec;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* The hash table. */
static struct bfd_hash_table already_linked_table;
@@ -865,6 +895,8 @@ section_already_linked (bfd *abfd, asect
const char *name;
struct already_linked *l;
struct already_linked_hash_entry *already_linked_list;
+ struct already_linked_section result;
+ asection *group;
/* If we are only reading symbols from this object, then we want to
discard all sections. */
@@ -876,7 +908,12 @@ section_already_linked (bfd *abfd, asect
flags = bfd_get_section_flags (abfd, sec);
- if ((flags & SEC_LINK_ONCE) == 0)
+ /* Check if it belongs to a section group. */
+ group = sec->group;
+
+ /* Return if it isn't a .gnu.linkonce section nor a member of a
+ group. */
+ if ((flags & SEC_LINK_ONCE) == 0 && group == NULL)
return;
/* FIXME: When doing a relocatable link, we may have trouble
@@ -902,6 +939,18 @@ section_already_linked (bfd *abfd, asect
((struct already_linked_hash_entry *)
bfd_hash_lookup (&already_linked_table, name, TRUE, FALSE));
+ if ((flags & SEC_LINK_ONCE) == 0)
+ {
+ /* If this is a member of a COMDAT group, go straight to comdat
+ and .gnu.linkonce check. Otherwise, just return. */
+ if ((group->flags
+ & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD))
+ == (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD))
+ goto comdat;
+ else
+ return;
+ }
+
for (l = already_linked_list->entry; l != NULL; l = l->next)
{
if (sec->comdat == NULL
@@ -957,6 +1006,26 @@ section_already_linked (bfd *abfd, asect
}
}
+comdat:
+ /* When we get here, we must be either a group member or a
+ .gnu.linkonce section. Check if a member of a COMDAT group
+ matches a .gnu.linkonce section and vice versa. */
+ result.sec = sec;
+ result.linked = NULL;
+ bfd_hash_traverse (&already_linked_table,
+ (bfd_boolean (*) (struct bfd_hash_entry *, void *))
+ try_match_symbols_in_sections,
+ &result);
+ if (result.linked)
+ {
+ sec->output_section = bfd_abs_section_ptr;
+ sec->kept_section = result.linked;
+
+ /* Also discard the group section. */
+ if (group != NULL)
+ group->output_section = bfd_abs_section_ptr;
+ }
+
/* This is the first section with this name. Record it. Allocate
the memory from the same obstack as the hash table is kept in. */
More information about the Binutils
mailing list