From 082b7297014d9ccc3990c3c6be689dd18946d826 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 21 Jul 2004 15:42:58 +0000 Subject: [PATCH] bfd/ 2004-07-21 H.J. Lu * 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. binutils/ 2004-07-21 H.J. Lu * objcopy.c (filter_symbols): Use bfd_coff_get_comdat_section to access comdat. * objdump.c (dump_section_header): Likewise. ld/ 2004-07-21 H.J. Lu * 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. --- bfd/ChangeLog | 75 +++++++++++++++++ bfd/aout-adobe.c | 2 + bfd/aout-target.h | 4 + bfd/aout-tic30.c | 4 + bfd/bfd-in.h | 23 ++++++ bfd/bfd-in2.h | 55 ++++++++----- bfd/binary.c | 2 + bfd/bout.c | 2 + bfd/coff-alpha.c | 2 + bfd/coff-mips.c | 2 + bfd/coff-rs6000.c | 2 + bfd/coff64-rs6000.c | 2 + bfd/coffcode.h | 17 ++-- bfd/coffgen.c | 9 ++ bfd/cofflink.c | 10 +-- bfd/ecoff.c | 4 +- bfd/elf-bfd.h | 2 + bfd/elflink.c | 86 ++++++++++++++++++++ bfd/elfxx-target.h | 5 ++ bfd/i386msdos.c | 2 + bfd/i386os9k.c | 2 + bfd/ieee.c | 2 + bfd/ihex.c | 2 + bfd/libbfd-in.h | 26 ++++++ bfd/libbfd.h | 26 ++++++ bfd/libcoff-in.h | 2 + bfd/libcoff.h | 2 + bfd/linker.c | 194 ++++++++++++++++++++++++++++++++++++++++++++ bfd/mach-o.c | 2 + bfd/mmo.c | 2 + bfd/nlm-target.h | 2 + bfd/oasys.c | 2 + bfd/pef.c | 1 + bfd/ppcboot.c | 2 + bfd/section.c | 24 +----- bfd/som.c | 2 + bfd/srec.c | 2 + bfd/targets.c | 7 +- bfd/tekhex.c | 2 + bfd/versados.c | 2 + bfd/vms.c | 2 + bfd/xcoff-target.h | 2 + bfd/xsym.c | 2 + binutils/ChangeLog | 6 ++ binutils/objcopy.c | 2 +- binutils/objdump.c | 7 +- ld/ChangeLog | 10 +++ ld/ldlang.c | 162 +----------------------------------- 48 files changed, 591 insertions(+), 218 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b7332517ad..fce9926e97 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,78 @@ +2004-07-21 H.J. Lu + + * 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 * elflink.c (elf_get_linked_section_vma, compare_link_order, diff --git a/bfd/aout-adobe.c b/bfd/aout-adobe.c index 2e3a65f8a5..6de2a31c75 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 5fb58d0066..a169704355 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 cf574ff043..a9c06ff3b4 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 f48e9d71fc..062e55e49f 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 502a01b5e4..f6618898f6 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 2669ed3f81..4335a28ed3 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 63c30844bc..fe0c867fc5 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 7f3f83137e..2acb800cb5 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 f351eb1409..39f7f22b8f 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 79c5ae1cec..ed4a242048 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 098ea420c6..e8abaa1a0b 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 d40cc80e9d..c9773a67fe 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 22a85b3f6e..b6fa5ca055 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 af6dd3d699..ddb56f4955 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 40faea70c3..eba6236fd6 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 ee6089427e..5e5068379a 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 1e04be854d..f75dbaca8d 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 a48b9f36d6..b4aa171c9f 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 65080e3c6d..aedcef0fcb 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 1a272d21aa..c4b9d1ee13 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 ac0dcc3798..d7baa88e21 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 e818034c8e..a7636a9027 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 1bfa220f94..31cc1ba1a5 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 095010c0fd..03005f9f83 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 589f88c08f..f3a0359106 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 fd3ecd1ea2..efb7b1f856 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 10b4467944..cd2adb5e51 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 194898c171..c4c05ab84d 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 03244620fd..1b7eb86a4e 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 cf84000ff6..30ae4b101f 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 7df9c87968..c99919af0a 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 8e63359c61..b52ae65a0a 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 5c80561fbf..49f8140214 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 e178f5830a..b9272dbba7 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 5903c1a025..4b40f1bf12 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 d75fa5113a..3002c0baee 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 0719d4f3af..a08cd0b510 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 b5ec8030be..a7a925470f 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 e454cf3af0..50b3487fbc 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 9d160e9d4a..640d0eb6c9 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 7bf3de72fa..9b80e3c5ac 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 aa44e971c6..3c4c84da9a 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 fe5664e91c..8ab3d7ac6f 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,9 @@ +2004-07-21 H.J. Lu + + * objcopy.c (filter_symbols): Use bfd_coff_get_comdat_section + to access comdat. + * objdump.c (dump_section_header): Likewise. + 2004-07-15 Aravinda PR * nlmconv.c (main): Pass map_file argument to link_inputs. diff --git a/binutils/objcopy.c b/binutils/objcopy.c index 44e93313e9..7fd671107f 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 6c42d3ad0d..683203f854 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 b34292d05a..25aa0a05a9 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,13 @@ +2004-07-21 H.J. Lu + + * 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 * ldlang.c (init_os): Make sure that the newly allocated userdata diff --git a/ld/ldlang.c b/ld/ldlang.c index 9ea28696a7..6cc05a67cf 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 -- 2.34.1