aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog75
-rw-r--r--bfd/aout-adobe.c2
-rw-r--r--bfd/aout-target.h4
-rw-r--r--bfd/aout-tic30.c4
-rw-r--r--bfd/bfd-in.h23
-rw-r--r--bfd/bfd-in2.h55
-rw-r--r--bfd/binary.c2
-rw-r--r--bfd/bout.c2
-rw-r--r--bfd/coff-alpha.c2
-rw-r--r--bfd/coff-mips.c2
-rw-r--r--bfd/coff-rs6000.c2
-rw-r--r--bfd/coff64-rs6000.c2
-rw-r--r--bfd/coffcode.h17
-rw-r--r--bfd/coffgen.c9
-rw-r--r--bfd/cofflink.c10
-rw-r--r--bfd/ecoff.c4
-rw-r--r--bfd/elf-bfd.h2
-rw-r--r--bfd/elflink.c86
-rw-r--r--bfd/elfxx-target.h5
-rw-r--r--bfd/i386msdos.c2
-rw-r--r--bfd/i386os9k.c2
-rw-r--r--bfd/ieee.c2
-rw-r--r--bfd/ihex.c2
-rw-r--r--bfd/libbfd-in.h26
-rw-r--r--bfd/libbfd.h26
-rw-r--r--bfd/libcoff-in.h2
-rw-r--r--bfd/libcoff.h2
-rw-r--r--bfd/linker.c194
-rw-r--r--bfd/mach-o.c2
-rw-r--r--bfd/mmo.c2
-rw-r--r--bfd/nlm-target.h2
-rw-r--r--bfd/oasys.c2
-rw-r--r--bfd/pef.c1
-rw-r--r--bfd/ppcboot.c2
-rw-r--r--bfd/section.c24
-rw-r--r--bfd/som.c2
-rw-r--r--bfd/srec.c2
-rw-r--r--bfd/targets.c7
-rw-r--r--bfd/tekhex.c2
-rw-r--r--bfd/versados.c2
-rw-r--r--bfd/vms.c2
-rw-r--r--bfd/xcoff-target.h2
-rw-r--r--bfd/xsym.c2
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/objcopy.c2
-rw-r--r--binutils/objdump.c7
-rw-r--r--ld/ChangeLog10
-rw-r--r--ld/ldlang.c162
48 files changed, 591 insertions, 218 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index b733251..fce9926 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,78 @@
+2004-07-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ * aout-adobe.c (aout_32_section_already_linked): Defined.
+ * aout-target.h (MY_section_already_linked): Likewise.
+ * aout-tic30.c (MY_section_already_linked): Likewise.
+ * binary.c (binary_section_already_linked): Likewise.
+ * bout.c (b_out_section_already_linked): Likewise.
+ * coff-alpha.c (_bfd_ecoff_section_already_linked): Likewise.
+ * coff-mips.c (_bfd_ecoff_section_already_linked): Likewise.
+ * coffcode.h (coff_section_already_linked): Likewise.
+ * i386msdos.c (msdos_section_already_linked): Likewise.
+ * i386os9k.c (os9k_section_already_linked): Likewise.
+ * ieee.c (ieee_section_already_linked): Likewise.
+ * ihex.c (ihex_section_already_linked): Likewise.
+ * mach-o.c (bfd_mach_o_section_already_linked): Likewise.
+ * mmo.c (mmo_section_already_linked): Likewise.
+ * nlm-target.h (nlm_section_already_linked): Likewise.
+ * oasys.c (oasys_section_already_linked): Likewise.
+ * pef.c (bfd_pef_section_already_linked): Likewise.
+ * ppcboot.c (ppcboot_section_already_linked): Likewise.
+ * som.c (som_bfd_discard_group): Likewise.
+ * srec.c (srec_section_already_linked): Likewise.
+ * tekhex.c (tekhex_section_already_linked): Likewise.
+ * versados.c (versados_section_already_linked): Likewise.
+ * vms.c (vms_section_already_linked): Likewise.
+ * coff-target.h (_bfd_xcoff_section_already_linked): Likewise.
+ * xsym.c (bfd_sym_section_already_linked): Likewise.
+
+ * bfd-in.h (bfd_section_already_linked_table_init): New.
+ (bfd_section_already_linked_table_free): Likewise.
+
+ * coff-rs6000.c (rs6000coff_vec): Add
+ _bfd_generic_section_already_linked.
+ (pmac_xcoff_vec): Likewise.
+ * coff64-rs6000.c (rs6000coff64_vec): Likewise.
+ (aix5coff64_vec): Likewise.
+
+ * elf-bfd.h (_bfd_elf_section_already_linked): New prototype.
+ * elflink.c (_bfd_elf_section_already_linked): New function.
+
+ * elfxx-target.h (bfd_elfNN_section_already_linked): Defined.
+
+ * libbfd-in.h (_bfd_nolink_section_already_linked): Defined.
+ (_bfd_generic_section_already_linked): New.
+ (bfd_section_already_linked_hash_entry): Likewise.
+ (bfd_section_already_linked): Likewise.
+ (bfd_section_already_linked_table_lookup): Likewise.
+ (bfd_section_already_linked_table_insert): Likewise.
+
+ * linker.c (bfd_section_already_linked): New.
+ (_bfd_section_already_linked_table): Likewise.
+ (bfd_section_already_linked_table_lookup): Likewise.
+ (bfd_section_already_linked_table_insert): Likewise.
+ (already_linked_newfunc): Likewise.
+ (bfd_section_already_linked_table_init): Likewise.
+ (bfd_section_already_linked_table_free): Likewise.
+ (_bfd_generic_section_already_linked): Likewise.
+
+ * section.c (bfd_section): Remove comdat.
+ (bfd_comdat_info): Moved to ...
+ * bfd-in.h (coff_comdat_info): Here.
+ (bfd_coff_get_comdat_section): New.
+ * coffgen.c (bfd_coff_get_comdat_section): Likewise.
+ * libcoff-in.h (coff_section_tdata): Add comdat.
+ * coffcode.h (handle_COMDAT): Updated.
+ * cofflink.c (coff_link_add_symbols): Likewise.
+ * ecoff.c (bfd_debug_section): Likewise.
+
+ * targets.c (bfd_target): Add _section_already_linked.
+ (BFD_JUMP_TABLE_LINK): Updated.
+
+ * bfd-in2.h: Regenerated.
+ * libbfd.h: Likewise.
+ * libcoff.h: Likewise.
+
2003-07-21 Paul Brook <paul@codesourcery.com>
* elflink.c (elf_get_linked_section_vma, compare_link_order,
diff --git a/bfd/aout-adobe.c b/bfd/aout-adobe.c
index 2e3a65f..6de2a31 100644
--- a/bfd/aout-adobe.c
+++ b/bfd/aout-adobe.c
@@ -518,6 +518,8 @@ aout_adobe_sizeof_headers (ignore_abfd, ignore)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#define aout_32_bfd_link_hash_table_create \
_bfd_generic_link_hash_table_create
#define aout_32_bfd_link_hash_table_free \
diff --git a/bfd/aout-target.h b/bfd/aout-target.h
index 5fb58d0..a169704 100644
--- a/bfd/aout-target.h
+++ b/bfd/aout-target.h
@@ -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_section_already_linked
+#define MY_section_already_linked \
+ _bfd_generic_section_already_linked
+#endif
#ifndef MY_bfd_reloc_type_lookup
#define MY_bfd_reloc_type_lookup NAME(aout,reloc_type_lookup)
#endif
diff --git a/bfd/aout-tic30.c b/bfd/aout-tic30.c
index cf574ff..a9c06ff 100644
--- a/bfd/aout-tic30.c
+++ b/bfd/aout-tic30.c
@@ -976,6 +976,10 @@ tic30_aout_set_arch_mach (abfd, arch, machine)
#ifndef MY_bfd_discard_group
#define MY_bfd_discard_group bfd_generic_discard_group
#endif
+#ifndef MY_section_already_linked
+#define MY_section_already_linked \
+ _bfd_generic_section_already_linked
+#endif
#ifndef MY_bfd_reloc_type_lookup
#define MY_bfd_reloc_type_lookup tic30_aout_reloc_type_lookup
#endif
diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h
index f48e9d7..062e55e 100644
--- a/bfd/bfd-in.h
+++ b/bfd/bfd-in.h
@@ -559,6 +559,9 @@ void bfd_putl16 (bfd_vma, void *);
bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean);
void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean);
+
+extern bfd_boolean bfd_section_already_linked_table_init (void);
+extern void bfd_section_already_linked_table_free (void);
/* Externally visible ECOFF routines. */
@@ -847,3 +850,23 @@ extern void bfd_elf32_ia64_after_parse
extern void bfd_elf64_ia64_after_parse
(int);
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct coff_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+extern struct coff_comdat_info *bfd_coff_get_comdat_section
+ (bfd *, struct bfd_section *);
+
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 502a01b..f661889 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -566,6 +566,9 @@ void bfd_putl16 (bfd_vma, void *);
bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean);
void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean);
+
+extern bfd_boolean bfd_section_already_linked_table_init (void);
+extern void bfd_section_already_linked_table_free (void);
/* Externally visible ECOFF routines. */
@@ -854,6 +857,26 @@ extern void bfd_elf32_ia64_after_parse
extern void bfd_elf64_ia64_after_parse
(int);
+/* This structure is used for a comdat section, as in PE. A comdat
+ section is associated with a particular symbol. When the linker
+ sees a comdat section, it keeps only one of the sections with a
+ given name and associated with a given symbol. */
+
+struct coff_comdat_info
+{
+ /* The name of the symbol associated with a comdat section. */
+ const char *name;
+
+ /* The local symbol table index of the symbol associated with a
+ comdat section. This is only meaningful to the object file format
+ specific code; it is not an index into the list returned by
+ bfd_canonicalize_symtab. */
+ long symbol;
+};
+
+extern struct coff_comdat_info *bfd_coff_get_comdat_section
+ (bfd *, struct bfd_section *);
+
/* Extracted from init.c. */
void bfd_init (void);
@@ -1019,23 +1042,6 @@ long bfd_get_size (bfd *abfd);
/* Extracted from bfdwin.c. */
/* Extracted from section.c. */
-/* This structure is used for a comdat section, as in PE. A comdat
- section is associated with a particular symbol. When the linker
- sees a comdat section, it keeps only one of the sections with a
- given name and associated with a given symbol. */
-
-struct bfd_comdat_info
-{
- /* The name of the symbol associated with a comdat section. */
- const char *name;
-
- /* The local symbol table index of the symbol associated with a
- comdat section. This is only meaningful to the object file format
- specific code; it is not an index into the list returned by
- bfd_canonicalize_symtab. */
- long symbol;
-};
-
typedef struct bfd_section
{
/* The name of the section; the name isn't a copy, the pointer is
@@ -1359,9 +1365,6 @@ typedef struct bfd_section
/* Entity size for merging purposes. */
unsigned int entsize;
- /* Optional information about a COMDAT entry; NULL if not COMDAT. */
- struct bfd_comdat_info *comdat;
-
/* Points to the kept section if this section is a link-once section,
and is discarded. */
struct bfd_section *kept_section;
@@ -4430,7 +4433,8 @@ typedef struct bfd_target
NAME##_bfd_gc_sections, \
NAME##_bfd_merge_sections, \
NAME##_bfd_is_group_section, \
- NAME##_bfd_discard_group
+ NAME##_bfd_discard_group, \
+ NAME##_section_already_linked \
int (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
bfd_byte * (*_bfd_get_relocated_section_contents)
@@ -4473,6 +4477,10 @@ typedef struct bfd_target
/* Discard members of a group. */
bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *);
+ /* Check if SEC has been already linked during a reloceatable or
+ final link. */
+ void (*_section_already_linked) (bfd *, struct bfd_section *);
+
/* Routines to handle dynamic symbols and relocs. */
#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
NAME##_get_dynamic_symtab_upper_bound, \
@@ -4530,6 +4538,11 @@ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec);
#define bfd_link_split_section(abfd, sec) \
BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec))
+void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+#define bfd_section_already_linked(abfd, sec) \
+ BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+
/* Extracted from simple.c. */
bfd_byte *bfd_simple_get_relocated_section_contents
(bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table);
diff --git a/bfd/binary.c b/bfd/binary.c
index 2669ed3..4335a28 100644
--- a/bfd/binary.c
+++ b/bfd/binary.c
@@ -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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/bout.c b/bfd/bout.c
index 63c3084..fe0c867 100644
--- a/bfd/bout.c
+++ b/bfd/bout.c
@@ -1487,6 +1487,8 @@ b_out_bfd_get_relocated_section_contents (output_bfd, link_info, link_order,
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#define aout_32_get_section_contents_in_window \
_bfd_generic_get_section_contents_in_window
diff --git a/bfd/coff-alpha.c b/bfd/coff-alpha.c
index 7f3f831..2acb800 100644
--- a/bfd/coff-alpha.c
+++ b/bfd/coff-alpha.c
@@ -2356,6 +2356,8 @@ static const struct ecoff_backend_data alpha_ecoff_backend_data =
#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_section_already_linked \
+ _bfd_generic_section_already_linked
const bfd_target ecoffalpha_little_vec =
{
diff --git a/bfd/coff-mips.c b/bfd/coff-mips.c
index f351eb1..39f7f22 100644
--- a/bfd/coff-mips.c
+++ b/bfd/coff-mips.c
@@ -1395,6 +1395,8 @@ static const struct ecoff_backend_data mips_ecoff_backend_data =
#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_section_already_linked \
+ _bfd_generic_section_already_linked
extern const bfd_target ecoff_big_vec;
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index 79c5ae1..ed4a242 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -4198,6 +4198,7 @@ const bfd_target rs6000coff_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_generic_section_already_linked,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -4443,6 +4444,7 @@ const bfd_target pmac_xcoff_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_generic_section_already_linked,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index 098ea42..e8abaa1 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -2739,6 +2739,7 @@ const bfd_target rs6000coff64_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_generic_section_already_linked,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
@@ -2985,6 +2986,7 @@ const bfd_target aix5coff64_vec =
bfd_generic_merge_sections,
bfd_generic_is_group_section,
bfd_generic_discard_group,
+ _bfd_generic_section_already_linked,
/* Dynamic */
_bfd_xcoff_get_dynamic_symtab_upper_bound,
diff --git a/bfd/coffcode.h b/bfd/coffcode.h
index d40cc80..c9773a6 100644
--- a/bfd/coffcode.h
+++ b/bfd/coffcode.h
@@ -965,12 +965,13 @@ handle_COMDAT (abfd, sec_flags, hdr, name, section)
Intel puts the two adjacent, but Alpha (at
least) spreads them out. */
- amt = sizeof (struct bfd_comdat_info);
- section->comdat = bfd_alloc (abfd, amt);
- if (section->comdat == NULL)
+ amt = sizeof (struct coff_comdat_info);
+ coff_section_data (abfd, section)->comdat
+ = bfd_alloc (abfd, amt);
+ if (coff_section_data (abfd, section)->comdat == NULL)
abort ();
- section->comdat->symbol =
+ coff_section_data (abfd, section)->comdat->symbol =
(esym - esymstart) / bfd_coff_symesz (abfd);
amt = strlen (symname) + 1;
@@ -979,7 +980,8 @@ handle_COMDAT (abfd, sec_flags, hdr, name, section)
abort ();
strcpy (newname, symname);
- section->comdat->name = newname;
+ coff_section_data (abfd, section)->comdat->name
+ = newname;
}
goto breakloop;
@@ -5586,6 +5588,11 @@ static const bfd_coff_backend_data ticoff1_swap_table =
#define coff_bfd_discard_group bfd_generic_discard_group
#endif
+#ifndef coff_section_already_linked
+#define coff_section_already_linked \
+ _bfd_generic_section_already_linked
+#endif
+
#define CREATE_BIG_COFF_TARGET_VEC(VAR, NAME, EXTRA_O_FLAGS, EXTRA_S_FLAGS, UNDER, ALTERNATIVE, SWAP_TABLE) \
const bfd_target VAR = \
{ \
diff --git a/bfd/coffgen.c b/bfd/coffgen.c
index 22a85b3..b6fa5ca 100644
--- a/bfd/coffgen.c
+++ b/bfd/coffgen.c
@@ -2496,3 +2496,12 @@ bfd_coff_set_symbol_class (abfd, symbol, class)
return TRUE;
}
+
+struct coff_comdat_info *
+bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec)
+{
+ if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+ return coff_section_data (abfd, sec)->comdat;
+ else
+ return NULL;
+}
diff --git a/bfd/cofflink.c b/bfd/cofflink.c
index af6dd3d..ddb56f4 100644
--- a/bfd/cofflink.c
+++ b/bfd/cofflink.c
@@ -435,18 +435,18 @@ coff_link_add_symbols (bfd *abfd,
if (obj_pe (abfd)
&& (classification == COFF_SYMBOL_GLOBAL
|| classification == COFF_SYMBOL_PE_SECTION)
- && section->comdat != NULL
+ && coff_section_data (abfd, section)->comdat != NULL
&& strncmp (name, "??_", 3) == 0
- && strcmp (name, section->comdat->name) == 0)
+ && strcmp (name, coff_section_data (abfd, section)->comdat->name) == 0)
{
if (*sym_hash == NULL)
*sym_hash = coff_link_hash_lookup (coff_hash_table (info),
name, FALSE, copy, FALSE);
if (*sym_hash != NULL
&& (*sym_hash)->root.type == bfd_link_hash_defined
- && (*sym_hash)->root.u.def.section->comdat != NULL
- && strcmp ((*sym_hash)->root.u.def.section->comdat->name,
- section->comdat->name) == 0)
+ && coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat != NULL
+ && strcmp (coff_section_data (abfd, (*sym_hash)->root.u.def.section)->comdat->name,
+ coff_section_data (abfd, section)->comdat->name) == 0)
addit = FALSE;
}
diff --git a/bfd/ecoff.c b/bfd/ecoff.c
index 40faea7..eba6236 100644
--- a/bfd/ecoff.c
+++ b/bfd/ecoff.c
@@ -92,8 +92,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, kept_section, moving_line_filepos, */
+ 0, NULL, 0,
/* target_index, used_by_bfd, constructor_chain, owner, */
0, NULL, NULL, NULL,
/* symbol, */
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index ee60894..5e50683 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1394,6 +1394,8 @@ extern bfd_boolean bfd_elf_is_group_section
(bfd *, const struct bfd_section *);
extern bfd_boolean bfd_elf_discard_group
(bfd *, struct bfd_section *);
+extern void _bfd_elf_section_already_linked
+ (bfd *, struct bfd_section *);
extern void bfd_elf_set_group_contents
(bfd *, asection *, void *);
extern void _bfd_elf_link_just_syms
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 1e04be8..f75dbac 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -9154,3 +9154,89 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info)
return ret;
}
+
+void
+_bfd_elf_section_already_linked (bfd *abfd, struct bfd_section * sec)
+{
+ flagword flags;
+ const char *name;
+ struct bfd_section_already_linked *l;
+ struct bfd_section_already_linked_hash_entry *already_linked_list;
+
+ flags = sec->flags;
+ if ((flags & SEC_LINK_ONCE) == 0)
+ return;
+
+ /* FIXME: When doing a relocatable link, we may have trouble
+ copying relocations in other sections that refer to local symbols
+ in the section being discarded. Those relocations will have to
+ be converted somehow; as of this writing I'm not sure that any of
+ the backends handle that correctly.
+
+ It is tempting to instead not discard link once sections when
+ doing a relocatable link (technically, they should be discarded
+ whenever we are building constructors). However, that fails,
+ because the linker winds up combining all the link once sections
+ into a single large link once section, which defeats the purpose
+ of having link once sections in the first place.
+
+ Also, not merging link once sections in a relocatable link
+ causes trouble for MIPS ELF, which relies on link once semantics
+ to handle the .reginfo section correctly. */
+
+ name = bfd_get_section_name (abfd, sec);
+
+ already_linked_list = bfd_section_already_linked_table_lookup (name);
+
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
+ {
+ /* We may have 3 different sections on the list: group section,
+ comdat section and linkonce section. SEC may be a linkonce or
+ group section. We match a group section with a group section,
+ a linkonce section with a linkonce section, and ignore comdat
+ section. */
+ if ((sec->flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP)
+ && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL)
+ {
+ /* The section has already been linked. See if we should
+ issue a warning. */
+ switch (flags & SEC_LINK_DUPLICATES)
+ {
+ default:
+ abort ();
+
+ case SEC_LINK_DUPLICATES_DISCARD:
+ break;
+
+ case SEC_LINK_DUPLICATES_ONE_ONLY:
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: ignoring duplicate section `%s'\n"),
+ bfd_archive_filename (abfd), name);
+ break;
+
+ case SEC_LINK_DUPLICATES_SAME_SIZE:
+ if (sec->size != l->sec->size)
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: duplicate section `%s' has different size\n"),
+ bfd_archive_filename (abfd), name);
+ break;
+ }
+
+ /* Set the output_section field so that lang_add_section
+ does not create a lang_input_section structure for this
+ section. Since there might be a symbol in the section
+ being discarded, we must retain a pointer to the section
+ which we are really going to use. */
+ sec->output_section = bfd_abs_section_ptr;
+ sec->kept_section = l->sec;
+
+ if (flags & SEC_GROUP)
+ bfd_elf_discard_group (abfd, sec);
+
+ return;
+ }
+ }
+
+ /* This is the first section with this name. Record it. */
+ bfd_section_already_linked_table_insert (already_linked_list, sec);
+}
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index a48b9f3..b4aa171 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -144,6 +144,11 @@
#define bfd_elfNN_bfd_discard_group bfd_elf_discard_group
#endif
+#ifndef bfd_elfNN_section_already_linked
+#define bfd_elfNN_section_already_linked \
+ _bfd_elf_section_already_linked
+#endif
+
#ifndef bfd_elfNN_bfd_make_debug_symbol
#define bfd_elfNN_bfd_make_debug_symbol \
((asymbol * (*) (bfd *, void *, unsigned long)) bfd_nullvoidptr)
diff --git a/bfd/i386msdos.c b/bfd/i386msdos.c
index 65080e3..aedcef0 100644
--- a/bfd/i386msdos.c
+++ b/bfd/i386msdos.c
@@ -177,6 +177,8 @@ msdos_set_section_contents (abfd, section, location, offset, count)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/i386os9k.c b/bfd/i386os9k.c
index 1a272d2..c4b9d1e 100644
--- a/bfd/i386os9k.c
+++ b/bfd/i386os9k.c
@@ -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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/ieee.c b/bfd/ieee.c
index ac0dcc3..d7baa88 100644
--- a/bfd/ieee.c
+++ b/bfd/ieee.c
@@ -4039,6 +4039,8 @@ ieee_bfd_debug_info_accumulate (abfd, section)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/ihex.c b/bfd/ihex.c
index e818034..a7636a9 100644
--- a/bfd/ihex.c
+++ b/bfd/ihex.c
@@ -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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 1bfa220..31cc1ba 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -375,6 +375,8 @@ extern bfd_boolean _bfd_generic_set_section_contents
((bfd_boolean (*) (bfd *, struct bfd_link_info *)) bfd_false)
#define _bfd_nolink_bfd_link_split_section \
((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false)
+#define _bfd_nolink_section_already_linked \
+ ((void (*) (bfd *, struct bfd_section *)) bfd_void)
/* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not
have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC
@@ -474,6 +476,9 @@ extern bfd_boolean _bfd_generic_final_link
extern bfd_boolean _bfd_generic_link_split_section
(bfd *, struct bfd_section *);
+extern void _bfd_generic_section_already_linked
+ (bfd *, struct bfd_section *);
+
/* Generic reloc_link_order processing routine. */
extern bfd_boolean _bfd_generic_reloc_link_order
(bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *);
@@ -653,3 +658,24 @@ extern bfd_boolean _bfd_sh_align_load_span
bfd_boolean (*) (bfd *, asection *, void *, bfd_byte *, bfd_vma),
void *, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *);
#endif
+
+/* This is the shape of the elements inside the already_linked hash
+ table. It maps a name onto a list of already_linked elements with
+ the same name. */
+
+struct bfd_section_already_linked_hash_entry
+{
+ struct bfd_hash_entry root;
+ struct bfd_section_already_linked *entry;
+};
+
+struct bfd_section_already_linked
+{
+ struct bfd_section_already_linked *next;
+ asection *sec;
+};
+
+extern struct bfd_section_already_linked_hash_entry *
+ bfd_section_already_linked_table_lookup (const char *);
+extern void bfd_section_already_linked_table_insert
+ (struct bfd_section_already_linked_hash_entry *, asection *);
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 095010c..03005f9 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -380,6 +380,8 @@ extern bfd_boolean _bfd_generic_set_section_contents
((bfd_boolean (*) (bfd *, struct bfd_link_info *)) bfd_false)
#define _bfd_nolink_bfd_link_split_section \
((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false)
+#define _bfd_nolink_section_already_linked \
+ ((void (*) (bfd *, struct bfd_section *)) bfd_void)
/* Routines to use for BFD_JUMP_TABLE_DYNAMIC for targets which do not
have dynamic symbols or relocs. Use BFD_JUMP_TABLE_DYNAMIC
@@ -479,6 +481,9 @@ extern bfd_boolean _bfd_generic_final_link
extern bfd_boolean _bfd_generic_link_split_section
(bfd *, struct bfd_section *);
+extern void _bfd_generic_section_already_linked
+ (bfd *, struct bfd_section *);
+
/* Generic reloc_link_order processing routine. */
extern bfd_boolean _bfd_generic_reloc_link_order
(bfd *, struct bfd_link_info *, asection *, struct bfd_link_order *);
@@ -658,6 +663,27 @@ extern bfd_boolean _bfd_sh_align_load_span
bfd_boolean (*) (bfd *, asection *, void *, bfd_byte *, bfd_vma),
void *, bfd_vma **, bfd_vma *, bfd_vma, bfd_vma, bfd_boolean *);
#endif
+
+/* This is the shape of the elements inside the already_linked hash
+ table. It maps a name onto a list of already_linked elements with
+ the same name. */
+
+struct bfd_section_already_linked_hash_entry
+{
+ struct bfd_hash_entry root;
+ struct bfd_section_already_linked *entry;
+};
+
+struct bfd_section_already_linked
+{
+ struct bfd_section_already_linked *next;
+ asection *sec;
+};
+
+extern struct bfd_section_already_linked_hash_entry *
+ bfd_section_already_linked_table_lookup (const char *);
+extern void bfd_section_already_linked_table_insert
+ (struct bfd_section_already_linked_hash_entry *, asection *);
/* Extracted from init.c. */
/* Extracted from libbfd.c. */
bfd_boolean bfd_write_bigendian_4byte_int (bfd *, unsigned int);
diff --git a/bfd/libcoff-in.h b/bfd/libcoff-in.h
index 589f88c..f3a0359 100644
--- a/bfd/libcoff-in.h
+++ b/bfd/libcoff-in.h
@@ -194,6 +194,8 @@ struct coff_section_tdata
bfd_vma offset;
unsigned int i;
const char *function;
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct coff_comdat_info *comdat;
int line_base;
/* A pointer used for .stab linking optimizations. */
PTR stab_info;
diff --git a/bfd/libcoff.h b/bfd/libcoff.h
index fd3ecd1..efb7b1f 100644
--- a/bfd/libcoff.h
+++ b/bfd/libcoff.h
@@ -198,6 +198,8 @@ struct coff_section_tdata
bfd_vma offset;
unsigned int i;
const char *function;
+ /* Optional information about a COMDAT entry; NULL if not COMDAT. */
+ struct coff_comdat_info *comdat;
int line_base;
/* A pointer used for .stab linking optimizations. */
PTR stab_info;
diff --git a/bfd/linker.c b/bfd/linker.c
index 10b4467..cd2adb5 100644
--- a/bfd/linker.c
+++ b/bfd/linker.c
@@ -2827,3 +2827,197 @@ _bfd_generic_link_split_section (bfd *abfd ATTRIBUTE_UNUSED,
{
return FALSE;
}
+
+/*
+FUNCTION
+ bfd_section_already_linked
+
+SYNOPSIS
+ void bfd_section_already_linked (bfd *abfd, asection *sec);
+
+DESCRIPTION
+ Check if @var{sec} has been already linked during a reloceatable
+ or final link.
+
+.#define bfd_section_already_linked(abfd, sec) \
+. BFD_SEND (abfd, _section_already_linked, (abfd, sec))
+.
+
+*/
+
+/* Sections marked with the SEC_LINK_ONCE flag should only be linked
+ once into the output. This routine checks each section, and
+ arrange to discard it if a section of the same name has already
+ been linked. This code assumes that all relevant sections have the
+ SEC_LINK_ONCE flag set; that is, it does not depend solely upon the
+ section name. bfd_section_already_linked is called via
+ bfd_map_over_sections. */
+
+/* The hash table. */
+
+static struct bfd_hash_table _bfd_section_already_linked_table;
+
+/* Support routines for the hash table used by section_already_linked,
+ initialize the table, lookup, fill in an entry and remove the
+ table. */
+
+struct bfd_section_already_linked_hash_entry *
+bfd_section_already_linked_table_lookup (const char *name)
+{
+ return ((struct bfd_section_already_linked_hash_entry *)
+ bfd_hash_lookup (&_bfd_section_already_linked_table, name,
+ TRUE, FALSE));
+}
+
+void
+bfd_section_already_linked_table_insert
+ (struct bfd_section_already_linked_hash_entry *already_linked_list,
+ asection *sec)
+{
+ struct bfd_section_already_linked *l;
+
+ /* Allocate the memory from the same obstack as the hash table is
+ kept in. */
+ l = bfd_hash_allocate (&_bfd_section_already_linked_table, sizeof *l);
+ l->sec = sec;
+ l->next = already_linked_list->entry;
+ already_linked_list->entry = l;
+}
+
+static struct bfd_hash_entry *
+already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED,
+ struct bfd_hash_table *table,
+ const char *string ATTRIBUTE_UNUSED)
+{
+ struct bfd_section_already_linked_hash_entry *ret =
+ bfd_hash_allocate (table, sizeof *ret);
+
+ ret->entry = NULL;
+
+ return &ret->root;
+}
+
+bfd_boolean
+bfd_section_already_linked_table_init (void)
+{
+ return bfd_hash_table_init_n (&_bfd_section_already_linked_table,
+ already_linked_newfunc, 42);
+}
+
+void
+bfd_section_already_linked_table_free (void)
+{
+ bfd_hash_table_free (&_bfd_section_already_linked_table);
+}
+
+/* This is used on non-ELF inputs. */
+
+void
+_bfd_generic_section_already_linked (bfd *abfd, asection *sec)
+{
+ flagword flags;
+ const char *name;
+ struct bfd_section_already_linked *l;
+ struct bfd_section_already_linked_hash_entry *already_linked_list;
+
+ flags = sec->flags;
+ if ((flags & SEC_LINK_ONCE) == 0)
+ return;
+
+ /* FIXME: When doing a relocatable link, we may have trouble
+ copying relocations in other sections that refer to local symbols
+ in the section being discarded. Those relocations will have to
+ be converted somehow; as of this writing I'm not sure that any of
+ the backends handle that correctly.
+
+ It is tempting to instead not discard link once sections when
+ doing a relocatable link (technically, they should be discarded
+ whenever we are building constructors). However, that fails,
+ because the linker winds up combining all the link once sections
+ into a single large link once section, which defeats the purpose
+ of having link once sections in the first place. */
+
+ name = bfd_get_section_name (abfd, sec);
+
+ already_linked_list = bfd_section_already_linked_table_lookup (name);
+
+ for (l = already_linked_list->entry; l != NULL; l = l->next)
+ {
+ bfd_boolean skip = FALSE;
+ struct coff_comdat_info *s_comdat
+ = bfd_coff_get_comdat_section (abfd, sec);
+ struct coff_comdat_info *l_comdat
+ = bfd_coff_get_comdat_section (l->sec->owner, l->sec);
+
+ /* We may have 3 different sections on the list: group section,
+ comdat section and linkonce section. SEC may be a linkonce or
+ comdat section. We always ignore group section. For non-COFF
+ inputs, we also ignore comdat section.
+
+ FIXME: Is that safe to match a linkonce section with a comdat
+ section for COFF inputs? */
+ if ((l->sec->flags & SEC_GROUP) != 0)
+ skip = TRUE;
+ else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour)
+ {
+ if (s_comdat != NULL
+ && l_comdat != NULL
+ && strcmp (s_comdat->name, l_comdat->name) != 0)
+ skip = TRUE;
+ }
+ else if (l_comdat != NULL)
+ skip = TRUE;
+
+ if (!skip)
+ {
+ /* The section has already been linked. See if we should
+ issue a warning. */
+ switch (flags & SEC_LINK_DUPLICATES)
+ {
+ default:
+ abort ();
+
+ case SEC_LINK_DUPLICATES_DISCARD:
+ break;
+
+ case SEC_LINK_DUPLICATES_ONE_ONLY:
+ if (s_comdat == NULL)
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: ignoring duplicate section `%s'\n"),
+ bfd_archive_filename (abfd), name);
+ else
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: ignoring duplicate `%s' section symbol `%s'\n"),
+ bfd_archive_filename (abfd), name, s_comdat->name);
+ break;
+
+ case SEC_LINK_DUPLICATES_SAME_CONTENTS:
+ /* FIXME: We should really dig out the contents of both
+ sections and memcmp them. The COFF/PE spec says that
+ the Microsoft linker does not implement this
+ correctly, so I'm not going to bother doing it
+ either. */
+ /* Fall through. */
+ case SEC_LINK_DUPLICATES_SAME_SIZE:
+ if (sec->size != l->sec->size)
+ (*_bfd_error_handler)
+ (_("%s: %s: warning: duplicate section `%s' has different size\n"),
+ bfd_archive_filename (abfd), name);
+ break;
+ }
+
+ /* Set the output_section field so that lang_add_section
+ does not create a lang_input_section structure for this
+ section. Since there might be a symbol in the section
+ being discarded, we must retain a pointer to the section
+ which we are really going to use. */
+ sec->output_section = bfd_abs_section_ptr;
+ sec->kept_section = l->sec;
+
+ return;
+ }
+ }
+
+ /* This is the first section with this name. Record it. */
+ bfd_section_already_linked_table_insert (already_linked_list, sec);
+}
diff --git a/bfd/mach-o.c b/bfd/mach-o.c
index 194898c..c4c05ab 100644
--- a/bfd/mach-o.c
+++ b/bfd/mach-o.c
@@ -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_section_already_linked \
+ _bfd_generic_section_already_linked
#define bfd_mach_o_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
static bfd_boolean bfd_mach_o_bfd_copy_private_symbol_data
diff --git a/bfd/mmo.c b/bfd/mmo.c
index 0324462..1b7eb86 100644
--- a/bfd/mmo.c
+++ b/bfd/mmo.c
@@ -3286,6 +3286,8 @@ mmo_canonicalize_reloc (abfd, section, relptr, symbols)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
/* 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
diff --git a/bfd/nlm-target.h b/bfd/nlm-target.h
index cf84000..30ae4b1 100644
--- a/bfd/nlm-target.h
+++ b/bfd/nlm-target.h
@@ -46,6 +46,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/oasys.c b/bfd/oasys.c
index 7df9c87..c99919a 100644
--- a/bfd/oasys.c
+++ b/bfd/oasys.c
@@ -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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/pef.c b/bfd/pef.c
index 8e63359..b52ae65 100644
--- a/bfd/pef.c
+++ b/bfd/pef.c
@@ -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_section_already_linked _bfd_generic_section_already_linked
#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
diff --git a/bfd/ppcboot.c b/bfd/ppcboot.c
index 5c80561..49f8140 100644
--- a/bfd/ppcboot.c
+++ b/bfd/ppcboot.c
@@ -471,6 +471,8 @@ ppcboot_bfd_print_private_bfd_data (abfd, farg)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/section.c b/bfd/section.c
index e178f58..b9272db 100644
--- a/bfd/section.c
+++ b/bfd/section.c
@@ -149,23 +149,6 @@ SUBSECTION
CODE_FRAGMENT
.
-.{* This structure is used for a comdat section, as in PE. A comdat
-. section is associated with a particular symbol. When the linker
-. sees a comdat section, it keeps only one of the sections with a
-. given name and associated with a given symbol. *}
-.
-.struct bfd_comdat_info
-.{
-. {* The name of the symbol associated with a comdat section. *}
-. const char *name;
-.
-. {* The local symbol table index of the symbol associated with a
-. comdat section. This is only meaningful to the object file format
-. specific code; it is not an index into the list returned by
-. bfd_canonicalize_symtab. *}
-. long symbol;
-.};
-.
.typedef struct bfd_section
.{
. {* The name of the section; the name isn't a copy, the pointer is
@@ -489,9 +472,6 @@ CODE_FRAGMENT
. {* Entity size for merging purposes. *}
. unsigned int entsize;
.
-. {* Optional information about a COMDAT entry; NULL if not COMDAT. *}
-. struct bfd_comdat_info *comdat;
-.
. {* Points to the kept section if this section is a link-once section,
. and is discarded. *}
. struct bfd_section *kept_section;
@@ -634,8 +614,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, kept_section, moving_line_filepos, */ \
+ 0, NULL, 0, \
\
/* target_index, used_by_bfd, constructor_chain, owner, */ \
0, NULL, NULL, NULL, \
diff --git a/bfd/som.c b/bfd/som.c
index 5903c1a..4b40f1b 100644
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -6404,6 +6404,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_section_already_linked \
+ _bfd_generic_section_already_linked
const bfd_target som_vec = {
"som", /* name */
diff --git a/bfd/srec.c b/bfd/srec.c
index d75fa51..3002c0b 100644
--- a/bfd/srec.c
+++ b/bfd/srec.c
@@ -1286,6 +1286,8 @@ srec_print_symbol (abfd, afile, symbol, how)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/targets.c b/bfd/targets.c
index 0719d4f..a08cd0b 100644
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -412,7 +412,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##_section_already_linked \
.
. int (*_bfd_sizeof_headers) (bfd *, bfd_boolean);
. bfd_byte * (*_bfd_get_relocated_section_contents)
@@ -455,6 +456,10 @@ BFD_JUMP_TABLE macros.
. {* Discard members of a group. *}
. bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *);
.
+. {* Check if SEC has been already linked during a reloceatable or
+. final link. *}
+. void (*_section_already_linked) (bfd *, struct bfd_section *);
+.
. {* Routines to handle dynamic symbols and relocs. *}
.#define BFD_JUMP_TABLE_DYNAMIC(NAME) \
. NAME##_get_dynamic_symtab_upper_bound, \
diff --git a/bfd/tekhex.c b/bfd/tekhex.c
index b5ec803..a7a9254 100644
--- a/bfd/tekhex.c
+++ b/bfd/tekhex.c
@@ -1003,6 +1003,8 @@ tekhex_print_symbol (abfd, filep, symbol, how)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/versados.c b/bfd/versados.c
index e454cf3..50b3487 100644
--- a/bfd/versados.c
+++ b/bfd/versados.c
@@ -874,6 +874,8 @@ versados_canonicalize_reloc (abfd, section, relptr, symbols)
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/bfd/vms.c b/bfd/vms.c
index 9d160e9..640d0eb 100644
--- a/bfd/vms.c
+++ b/bfd/vms.c
@@ -168,6 +168,8 @@ static bfd_boolean vms_bfd_set_private_flags
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#define vms_bfd_copy_private_header_data \
_bfd_generic_bfd_copy_private_header_data
diff --git a/bfd/xcoff-target.h b/bfd/xcoff-target.h
index 7bf3de7..9b80e3c 100644
--- a/bfd/xcoff-target.h
+++ b/bfd/xcoff-target.h
@@ -99,6 +99,8 @@ extern int lynx_core_file_failing_signal PARAMS ((bfd *abfd));
#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_section_already_linked \
+ _bfd_generic_section_already_linked
#define _bfd_xcoff_bfd_link_split_section coff_bfd_link_split_section
/* XCOFF archives do not have anything which corresponds to an
diff --git a/bfd/xsym.c b/bfd/xsym.c
index aa44e97..3c4c84d 100644
--- a/bfd/xsym.c
+++ b/bfd/xsym.c
@@ -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_section_already_linked \
+ _bfd_generic_section_already_linked
#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
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index fe5664e..8ab3d7a 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,9 @@
+2004-07-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ * objcopy.c (filter_symbols): Use bfd_coff_get_comdat_section
+ to access comdat.
+ * objdump.c (dump_section_header): Likewise.
+
2004-07-15 Aravinda PR <aravindapr@rediffmail.com>
* nlmconv.c (main): Pass map_file argument to link_inputs.
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 44e9331..7fd6711 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -891,7 +891,7 @@ filter_symbols (bfd *abfd, bfd *obfd, asymbol **osyms,
keep = (strip_symbols != STRIP_DEBUG
&& strip_symbols != STRIP_UNNEEDED
&& ! convert_debugging);
- else if (bfd_get_section (sym)->comdat)
+ else if (bfd_coff_get_comdat_section (abfd, bfd_get_section (sym)))
/* COMDAT sections store special information in local
symbols, so we cannot risk stripping any of them. */
keep = 1;
diff --git a/binutils/objdump.c b/binutils/objdump.c
index 6c42d3a..683203f 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -331,6 +331,7 @@ dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
if ((section->flags & SEC_LINK_ONCE) != 0)
{
const char *ls;
+ struct coff_comdat_info *comdat;
switch (section->flags & SEC_LINK_DUPLICATES)
{
@@ -351,9 +352,9 @@ dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, asection *section,
}
printf ("%s%s", comma, ls);
- if (section->comdat != NULL)
- printf (" (COMDAT %s %ld)", section->comdat->name,
- section->comdat->symbol);
+ comdat = bfd_coff_get_comdat_section (abfd, section);
+ if (comdat != NULL)
+ printf (" (COMDAT %s %ld)", comdat->name, comdat->symbol);
comma = ", ";
}
diff --git a/ld/ChangeLog b/ld/ChangeLog
index b34292d..25aa0a0 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,13 @@
+2004-07-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ * ldlang.c (already_linked_hash_entry): Removed.
+ (already_linked): Likewise.
+ (already_linked_table): Likewise.
+ (section_already_linked): Call bfd_section_already_linked.
+ (lang_process): Replace already_linked_table_init with
+ bfd_section_already_linked_table_init and check return. Replace
+ already_linked_table_free with bfd_section_already_linked_table_free.
+
2004-07-21 Nick Clifton <nickc@redhat.com>
* ldlang.c (init_os): Make sure that the newly allocated userdata
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 9ea2869..6cc05a6 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -886,44 +886,10 @@ exp_init_os (etree_type *exp)
}
}
-/* Sections marked with the SEC_LINK_ONCE flag should only be linked
- once into the output. This routine checks each section, and
- arrange to discard it if a section of the same name has already
- been linked. If the section has COMDAT information, then it uses
- that to decide whether the section should be included. This code
- assumes that all relevant sections have the SEC_LINK_ONCE flag set;
- that is, it does not depend solely upon the section name.
- section_already_linked is called via bfd_map_over_sections. */
-
-/* This is the shape of the elements inside the already_linked hash
- table. It maps a name onto a list of already_linked elements with
- the same name. It's possible to get more than one element in a
- list if the COMDAT sections have different names. */
-
-struct already_linked_hash_entry
-{
- struct bfd_hash_entry root;
- struct already_linked *entry;
-};
-
-struct already_linked
-{
- struct already_linked *next;
- asection *sec;
-};
-
-/* The hash table. */
-
-static struct bfd_hash_table already_linked_table;
-
static void
section_already_linked (bfd *abfd, asection *sec, void *data)
{
lang_input_statement_type *entry = data;
- flagword flags;
- const char *name;
- struct already_linked *l;
- struct already_linked_hash_entry *already_linked_list;
/* If we are only reading symbols from this object, then we want to
discard all sections. */
@@ -933,128 +899,7 @@ section_already_linked (bfd *abfd, asection *sec, void *data)
return;
}
- flags = sec->flags;
- if ((flags & SEC_LINK_ONCE) == 0)
- return;
-
- /* FIXME: When doing a relocatable link, we may have trouble
- copying relocations in other sections that refer to local symbols
- in the section being discarded. Those relocations will have to
- be converted somehow; as of this writing I'm not sure that any of
- the backends handle that correctly.
-
- It is tempting to instead not discard link once sections when
- doing a relocatable link (technically, they should be discarded
- whenever we are building constructors). However, that fails,
- because the linker winds up combining all the link once sections
- into a single large link once section, which defeats the purpose
- of having link once sections in the first place.
-
- Also, not merging link once sections in a relocatable link
- causes trouble for MIPS ELF, which relies on link once semantics
- to handle the .reginfo section correctly. */
-
- name = bfd_get_section_name (abfd, sec);
-
- already_linked_list =
- ((struct already_linked_hash_entry *)
- bfd_hash_lookup (&already_linked_table, name, TRUE, FALSE));
-
- for (l = already_linked_list->entry; l != NULL; l = l->next)
- {
- if (sec->comdat == NULL
- || l->sec->comdat == NULL
- || strcmp (sec->comdat->name, l->sec->comdat->name) == 0)
- {
- /* The section has already been linked. See if we should
- issue a warning. */
- switch (flags & SEC_LINK_DUPLICATES)
- {
- default:
- abort ();
-
- case SEC_LINK_DUPLICATES_DISCARD:
- break;
-
- case SEC_LINK_DUPLICATES_ONE_ONLY:
- if (sec->comdat == NULL)
- einfo (_("%P: %B: warning: ignoring duplicate section `%s'\n"),
- abfd, name);
- else
- einfo (_("%P: %B: warning: ignoring duplicate `%s'"
- " section symbol `%s'\n"),
- abfd, name, sec->comdat->name);
- break;
-
- case SEC_LINK_DUPLICATES_SAME_CONTENTS:
- /* FIXME: We should really dig out the contents of both
- sections and memcmp them. The COFF/PE spec says that
- the Microsoft linker does not implement this
- correctly, so I'm not going to bother doing it
- either. */
- /* Fall through. */
- case SEC_LINK_DUPLICATES_SAME_SIZE:
- if (sec->size != l->sec->size)
- einfo (_("%P: %B: warning: duplicate section `%s'"
- " has different size\n"),
- abfd, name);
- break;
- }
-
- /* Set the output_section field so that lang_add_section
- does not create a lang_input_section structure for this
- section. Since there might be a symbol in the section
- being discarded, we must retain a pointer to the section
- which we are really going to use. */
- sec->output_section = bfd_abs_section_ptr;
- sec->kept_section = l->sec;
-
- if (flags & SEC_GROUP)
- bfd_discard_group (abfd, sec);
-
- return;
- }
- }
-
- /* This is the first section with this name. Record it. Allocate
- the memory from the same obstack as the hash table is kept in. */
-
- l = bfd_hash_allocate (&already_linked_table, sizeof *l);
-
- l->sec = sec;
- l->next = already_linked_list->entry;
- already_linked_list->entry = l;
-}
-
-/* Support routines for the hash table used by section_already_linked,
- initialize the table, fill in an entry and remove the table. */
-
-static struct bfd_hash_entry *
-already_linked_newfunc (struct bfd_hash_entry *entry ATTRIBUTE_UNUSED,
- struct bfd_hash_table *table,
- const char *string ATTRIBUTE_UNUSED)
-{
- struct already_linked_hash_entry *ret =
- bfd_hash_allocate (table, sizeof (struct already_linked_hash_entry));
-
- ret->entry = NULL;
-
- return &ret->root;
-}
-
-static void
-already_linked_table_init (void)
-{
- if (! bfd_hash_table_init_n (&already_linked_table,
- already_linked_newfunc,
- 42))
- einfo (_("%P%F: Failed to create hash table\n"));
-}
-
-static void
-already_linked_table_free (void)
-{
- bfd_hash_table_free (&already_linked_table);
+ bfd_section_already_linked (abfd, sec);
}
/* The wild routines.
@@ -4347,7 +4192,8 @@ lang_process (void)
/* Add to the hash table all undefineds on the command line. */
lang_place_undefineds ();
- already_linked_table_init ();
+ if (!bfd_section_already_linked_table_init ())
+ einfo (_("%P%F: Failed to create hash table\n"));
/* Create a bfd for each input file. */
current_target = default_target;
@@ -4359,7 +4205,7 @@ lang_process (void)
ldemul_after_open ();
- already_linked_table_free ();
+ bfd_section_already_linked_table_free ();
/* Make sure that we're not mixing architectures. We call this
after all the input files have been opened, but before we do any