* section.c (SEC_LINK_ONCE): Define.
authorIan Lance Taylor <ian@airs.com>
Fri, 29 Mar 1996 21:33:59 +0000 (21:33 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 29 Mar 1996 21:33:59 +0000 (21:33 +0000)
(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
bfd/bfd-in2.h
bfd/coff-ppc.c
bfd/coffcode.h
bfd/coffgen.c

index 138afbc..be95467 100644 (file)
@@ -1,5 +1,27 @@
 Fri Mar 29 12:44:36 1996  Ian Lance Taylor  <ian@cygnus.com>
 
+       * 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.
 
index 148ee13..cd0f8d7 100644 (file)
@@ -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.  */
index efc3776..d49348f 100644 (file)
@@ -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 */
index 0a7c730..7f15ef8 100644 (file)
@@ -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:
index bb9882b..14df3a3 100644 (file)
@@ -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);