From 5a28331f6dc965462a5380c381283b26edd283ca Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 29 Mar 1996 21:33:59 +0000 Subject: [PATCH] * section.c (SEC_LINK_ONCE): Define. (SEC_LINK_DUPLICATES): Define. (SEC_LINK_DUPLICATES_DISCARD): Define. (SEC_LINK_DUPLICATES_ONE_ONLY): Define. (SEC_LINK_DUPLICATES_SAME_SIZE): Define. (SEC_LINK_DUPLICATES_SAME_CONTENTS): Define. * bfd-in2.h: Rebuild. * coffcode.h (sec_to_styp_flags): If COFF_WITH_PE, turn SEC_LINK_ONCE into IMAGE_SCN_LNK_COMDAT. (styp_to_sec_flags): If COFF_WITH_PE, turn IMAGE_SCN_LNK_REMOVE into SEC_EXCLUDE. If IMAGE_SCN_LNK_COMDAT is set, set SEC_LINK_ONCE, and look through the symbol table for the setting for SEC_LINK_DUPLICATES. (coff_write_object_contents): If COFF_WITH_PE, if SEC_LINK_ONCE is set for a section, find the section symbol in the symbol table, and set the aux entry based on SEC_LINK_DUPLICATES. * coffgen.c (coff_print_symbol): Add a space before "checksum". * coff-arm.c (armcoff_big_vec): If COFF_WITH_PE is defined, add SEC_LINK_ONCE and SEC_LINK_DUPLICATES to section_flags. * coff-i386.c (i386coff_vec): Likewise. * coff-ppc.c (TARGET_LITTLE_SYM, TARGET_BIG_SYM): Likewise. --- bfd/ChangeLog | 22 +++++++ bfd/bfd-in2.h | 30 ++++++++- bfd/coff-ppc.c | 12 ++++ bfd/coffcode.h | 175 +++++++++++++++++++++++++++++++++++++++++++++---- bfd/coffgen.c | 2 +- 5 files changed, 227 insertions(+), 14 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 138afbc6da2..be954678718 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,27 @@ Fri Mar 29 12:44:36 1996 Ian Lance Taylor + * section.c (SEC_LINK_ONCE): Define. + (SEC_LINK_DUPLICATES): Define. + (SEC_LINK_DUPLICATES_DISCARD): Define. + (SEC_LINK_DUPLICATES_ONE_ONLY): Define. + (SEC_LINK_DUPLICATES_SAME_SIZE): Define. + (SEC_LINK_DUPLICATES_SAME_CONTENTS): Define. + * bfd-in2.h: Rebuild. + * coffcode.h (sec_to_styp_flags): If COFF_WITH_PE, turn + SEC_LINK_ONCE into IMAGE_SCN_LNK_COMDAT. + (styp_to_sec_flags): If COFF_WITH_PE, turn IMAGE_SCN_LNK_REMOVE + into SEC_EXCLUDE. If IMAGE_SCN_LNK_COMDAT is set, set + SEC_LINK_ONCE, and look through the symbol table for the setting + for SEC_LINK_DUPLICATES. + (coff_write_object_contents): If COFF_WITH_PE, if SEC_LINK_ONCE is + set for a section, find the section symbol in the symbol table, + and set the aux entry based on SEC_LINK_DUPLICATES. + * coffgen.c (coff_print_symbol): Add a space before "checksum". + * coff-arm.c (armcoff_big_vec): If COFF_WITH_PE is defined, add + SEC_LINK_ONCE and SEC_LINK_DUPLICATES to section_flags. + * coff-i386.c (i386coff_vec): Likewise. + * coff-ppc.c (TARGET_LITTLE_SYM, TARGET_BIG_SYM): Likewise. + * VERSION: Bump to 2.6.1. * Makefile.in (stamp-h): Depend upon VERSION. diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 148ee131d15..cd0f8d769d7 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -862,7 +862,7 @@ typedef struct sec sections. */ #define SEC_COFF_SHARED_LIBRARY 0x800 - /* The section is a common section (symbols may be defined + /* The section contains common symbols (symbols may be defined multiple times, the value of a symbol is the amount of space it requires, and the largest symbol value is the one used). Most targets have exactly one of these (which we @@ -891,6 +891,34 @@ typedef struct sec table. */ #define SEC_SORT_ENTRIES 0x80000 + /* When linking, duplicate sections of the same name should be + discarded, rather than being combined into a single section as + is usually done. This is similar to how common symbols are + handled. See SEC_LINK_DUPLICATES below. */ +#define SEC_LINK_ONCE 0x100000 + + /* If SEC_LINK_ONCE is set, this bitfield describes how the linker + should handle duplicate sections. */ +#define SEC_LINK_DUPLICATES 0x600000 + + /* This value for SEC_LINK_DUPLICATES means that duplicate + sections with the same name should simply be discarded. */ +#define SEC_LINK_DUPLICATES_DISCARD 0x0 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if there are any duplicate sections, although + it should still only link one copy. */ +#define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections are a different size. */ +#define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections contain different + contents. */ +#define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000 + /* End of section flags. */ /* Some internal packed boolean fields. */ diff --git a/bfd/coff-ppc.c b/bfd/coff-ppc.c index efc37767b22..d49348fd586 100644 --- a/bfd/coff-ppc.c +++ b/bfd/coff-ppc.c @@ -3191,7 +3191,13 @@ TARGET_LITTLE_SYM = HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | WP_TEXT), +#ifndef COFF_WITH_PE (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ +#else + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */ + | SEC_LINK_ONCE | SEC_LINK_DUPLICATES), +#endif + 0, /* leading char */ '/', /* ar_pad_char */ 15, /* ar_max_namelen??? FIXMEmgo */ @@ -3238,7 +3244,13 @@ TARGET_BIG_SYM = HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS | WP_TEXT), +#ifndef COFF_WITH_PE (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */ +#else + (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */ + | SEC_LINK_ONCE | SEC_LINK_DUPLICATES), +#endif + 0, /* leading char */ '/', /* ar_pad_char */ 15, /* ar_max_namelen??? FIXMEmgo */ diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 0a7c730729e..7f15ef8f04f 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -414,6 +414,11 @@ sec_to_styp_flags (sec_name, sec_flags) styp_flags |= STYP_NOLOAD; #endif +#ifdef COFF_WITH_PE + if (sec_flags & SEC_LINK_ONCE) + styp_flags |= IMAGE_SCN_LNK_COMDAT; +#endif + return (styp_flags); } /* @@ -542,6 +547,96 @@ styp_to_sec_flags (abfd, hdr, name) } #endif /* STYP_SDATA */ +#ifdef COFF_WITH_PE + if (styp_flags & IMAGE_SCN_LNK_REMOVE) + sec_flags |= SEC_EXCLUDE; + + if (styp_flags & IMAGE_SCN_LNK_COMDAT) + { + sec_flags |= SEC_LINK_ONCE; + + /* Unfortunately, the PE format stores essential information in + the symbol table, of all places. We need to extract that + information now, so that objdump and the linker will know how + to handle the section without worrying about the symbols. We + can't call slurp_symtab, because the linker doesn't want the + swapped symbols. */ + + if (_bfd_coff_get_external_symbols (abfd)) + { + bfd_byte *esym, *esymend; + + esym = (bfd_byte *) obj_coff_external_syms (abfd); + esymend = esym + obj_raw_syment_count (abfd) * SYMESZ; + + while (esym < esymend) + { + struct internal_syment isym; + + bfd_coff_swap_sym_in (abfd, (PTR) esym, (PTR) &isym); + + if (sizeof (internal_s->s_name) > SYMNMLEN) + { + /* This case implies that the matching symbol name + will be in the string table. */ + abort (); + } + + if (isym.n_sclass == C_STAT + && isym.n_type == T_NULL + && isym.n_numaux == 1 + && isym._n._n_n._n_zeroes != 0) + { + char buf[SYMNMLEN + 1]; + + memcpy (buf, isym._n._n_name, SYMNMLEN); + buf[SYMNMLEN] = '\0'; + + if (strcmp (name, buf) == 0) + { + union internal_auxent aux; + + /* This is the section symbol. */ + + bfd_coff_swap_aux_in (abfd, (PTR) (esym + SYMESZ), + isym.n_type, isym.n_sclass, + 0, isym.n_numaux, (PTR) &aux); + + switch (aux.x_scn.x_comdat) + { + case IMAGE_COMDAT_SELECT_NODUPLICATES: + sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY; + break; + + default: + case IMAGE_COMDAT_SELECT_ANY: + sec_flags |= SEC_LINK_DUPLICATES_DISCARD; + break; + + case IMAGE_COMDAT_SELECT_SAME_SIZE: + sec_flags |= SEC_LINK_DUPLICATES_SAME_SIZE; + break; + + case IMAGE_COMDAT_SELECT_EXACT_MATCH: + sec_flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS; + break; + + case IMAGE_COMDAT_SELECT_ASSOCIATIVE: + /* FIXME: This is not currently implemented. */ + sec_flags |= SEC_LINK_DUPLICATES_DISCARD; + break; + } + + break; + } + } + + esym += (isym.n_numaux + 1) * SYMESZ; + } + } + } +#endif + return (sec_flags); } @@ -2361,6 +2456,63 @@ coff_write_object_contents (abfd) || bfd_write ((PTR) (&buff), 1, SCNHSZ, abfd) != SCNHSZ) return false; } + +#ifdef COFF_WITH_PE + /* PE stores COMDAT section information in the symbol table. If + this section is supposed to have some COMDAT info, track down + the symbol in the symbol table and modify it. */ + if ((current->flags & SEC_LINK_ONCE) != 0) + { + unsigned int i, count; + asymbol **psym; + + count = bfd_get_symcount (abfd); + for (i = 0, psym = abfd->outsymbols; i < count; i++, psym++) + { + coff_symbol_type *csym; + combined_entry_type *aux; + + if (strcmp ((*psym)->name, current->name) != 0) + continue; + + csym = coff_symbol_from (abfd, *psym); + if (csym == NULL + || csym->native == NULL + || csym->native->u.syment.n_numaux < 1 + || csym->native->u.syment.n_sclass != C_STAT + || csym->native->u.syment.n_type != T_NULL) + continue; + + /* Here *PSYM is the section symbol for CURRENT. */ + + /* We don't touch the x_checksum field. The + x_associated field is not currently supported. */ + + aux = csym->native + 1; + switch (current->flags & SEC_LINK_DUPLICATES) + { + case SEC_LINK_DUPLICATES_DISCARD: + aux->u.auxent.x_scn.x_comdat = IMAGE_COMDAT_SELECT_ANY; + break; + + case SEC_LINK_DUPLICATES_ONE_ONLY: + aux->u.auxent.x_scn.x_comdat = + IMAGE_COMDAT_SELECT_NODUPLICATES; + break; + + case SEC_LINK_DUPLICATES_SAME_SIZE: + aux->u.auxent.x_scn.x_comdat = + IMAGE_COMDAT_SELECT_SAME_SIZE; + break; + + case SEC_LINK_DUPLICATES_SAME_CONTENTS: + aux->u.auxent.x_scn.x_comdat = + IMAGE_COMDAT_SELECT_EXACT_MATCH; + break; + } + } + } +#endif /* COFF_WITH_PE */ } #ifdef RS6000COFF_C @@ -3055,15 +3207,14 @@ coff_slurp_symbol_table (abfd) dst->symbol.flags = BSF_DEBUGGING; else dst->symbol.flags = BSF_LOCAL; - /* - Base the value as an index from the base of the section, if - there is one - */ + + /* Base the value as an index from the base of the + section, if there is one. */ if (dst->symbol.section) - dst->symbol.value = (src->u.syment.n_value) - - dst->symbol.section->vma; + dst->symbol.value = (src->u.syment.n_value + - dst->symbol.section->vma); else - dst->symbol.value = (src->u.syment.n_value); + dst->symbol.value = src->u.syment.n_value; break; case C_MOS: /* member of structure */ @@ -3154,13 +3305,13 @@ coff_slurp_symbol_table (abfd) #endif case C_BLOCK: /* ".bb" or ".eb" */ - case C_FCN: /* ".bf" or ".ef" */ + case C_FCN: /* ".bf" or ".ef" */ case C_EFCN: /* physical end of function */ dst->symbol.flags = BSF_LOCAL; - /* - Base the value as an index from the base of the section - */ - dst->symbol.value = (src->u.syment.n_value) - dst->symbol.section->vma; + /* Base the value as an index from the base of the + section. */ + dst->symbol.value = (src->u.syment.n_value + - dst->symbol.section->vma); break; case C_NULL: diff --git a/bfd/coffgen.c b/bfd/coffgen.c index bb9882b7e60..14df3a3f729 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1877,7 +1877,7 @@ coff_print_symbol (abfd, filep, symbol, how) if (auxp->u.auxent.x_scn.x_checksum != 0 || auxp->u.auxent.x_scn.x_associated != 0 || auxp->u.auxent.x_scn.x_comdat != 0) - fprintf (file, "checksum 0x%lx assoc %d comdat %d", + fprintf (file, " checksum 0x%lx assoc %d comdat %d", auxp->u.auxent.x_scn.x_checksum, auxp->u.auxent.x_scn.x_associated, auxp->u.auxent.x_scn.x_comdat); -- 2.30.2