OSDN Git Service

* som.c (struct som_misc_symbol_info): Add is_comdat, is_common and
authorDave Anglin <dave.anglin@nrc.ca>
Wed, 28 Apr 2004 18:02:49 +0000 (18:02 +0000)
committerDave Anglin <dave.anglin@nrc.ca>
Wed, 28 Apr 2004 18:02:49 +0000 (18:02 +0000)
dup_common fields.
(setup_sections): Use som_subspace_dictionary_record struct instead
subspace_dictionary_record.  Set SEC_LINK_ONCE if subspace is
is_comdat, is_common or dup_common.
(som_prep_headers): Use som_subspace_dictionary_record struct.  Set
is_comdat, is_common and dup_common in section subspace_dict from
copy_data.
(som_begin_writing): Use som_subspace_dictionary_record struct.
(som_finish_writing): Likewise.
(som_bfd_derive_misc_symbol_info): Add support to set is_comdat,
is_common and dup_common flags in info for symbol.  Add comment
regarding linker support for these fields.  Slightly reorganize
function.
(som_build_and_write_symbol_table): Set is_comdat, is_common and
dup_common fields in symbol table from symbol info.
(bfd_som_set_subsection_attributes): Add comdat, common and dup_common
arguments.  Set corresponding fields in copy_data.  Change all callers.
(som_bfd_ar_write_symbol_stuff): Set dup_common flag in library
symbol table.
(som_vec): Add SEC_LINK_ONCE to applicable section flags.
* som.h (som_subspace_dictionary_record): Define.
(som_copyable_section_data_struct): Add is_comdat, is_common and
dup_common fields.
(som_section_data_struct): Use som_subspace_dictionary_record struct
instead of subspace_dictionary_record.
(bfd_boolean bfd_som_set_subsection_attributes): Adjust prototype.
* config/obj-som.c (obj_som_init_stab_section): Add new arguments in
call to obj_set_subsection_attributes.
(obj_som_init_stab_section): Likewise.
* config/tc-hppa.c (default_subspace_dict): Add comdat field.
(pa_def_subspaces): Provide comdat default.
(pa_subspace): Handle new "comdat" parameter.  Set SEC_LINK_ONCE and
not SEC_IS_COMMON if section is comdat, common or dup_common.  Update
calls to create_new_subspace and update_subspace to pass comdat flag.
(create_new_subspace, update_subspace): Add new comdat argument.  Use
it in calls to obj_set_subsection_attributes.
* doc/c-hppa.texi (.subspa, .nsubspa): Document new comdat parameter
and use of comdat, common and dup_comm parameters.

bfd/ChangeLog
bfd/som.c
bfd/som.h
gas/ChangeLog
gas/config/obj-som.c
gas/config/tc-hppa.c
gas/doc/c-hppa.texi

index 9962fb5..8fbe78e 100644 (file)
@@ -1,3 +1,33 @@
+2004-04-28  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       * som.c (struct som_misc_symbol_info): Add is_comdat, is_common and
+       dup_common fields.
+       (setup_sections): Use som_subspace_dictionary_record struct instead
+       subspace_dictionary_record.  Set SEC_LINK_ONCE if subspace is
+       is_comdat, is_common or dup_common.
+       (som_prep_headers): Use som_subspace_dictionary_record struct.  Set
+       is_comdat, is_common and dup_common in section subspace_dict from
+       copy_data.
+       (som_begin_writing): Use som_subspace_dictionary_record struct.
+       (som_finish_writing): Likewise.
+       (som_bfd_derive_misc_symbol_info): Add support to set is_comdat,
+       is_common and dup_common flags in info for symbol.  Add comment
+       regarding linker support for these fields.  Slightly reorganize
+       function.
+       (som_build_and_write_symbol_table): Set is_comdat, is_common and
+       dup_common fields in symbol table from symbol info.
+       (bfd_som_set_subsection_attributes): Add comdat, common and dup_common
+       arguments.  Set corresponding fields in copy_data.  Change all callers.
+       (som_bfd_ar_write_symbol_stuff): Set dup_common flag in library
+       symbol table.
+       (som_vec): Add SEC_LINK_ONCE to applicable section flags.
+       * som.h (som_subspace_dictionary_record): Define.
+       (som_copyable_section_data_struct): Add is_comdat, is_common and
+       dup_common fields.
+       (som_section_data_struct): Use som_subspace_dictionary_record struct
+       instead of subspace_dictionary_record.
+       (bfd_boolean bfd_som_set_subsection_attributes): Adjust prototype.
+
 2004-04-27  Bob Wilson  <bob.wilson@acm.org>
 
        * elf32-xtensa.c (xtensa_read_table_entries): Use section _cooked_size
index 1d2d99e..6f05391 100644 (file)
--- a/bfd/som.c
+++ b/bfd/som.c
@@ -146,6 +146,9 @@ struct som_misc_symbol_info {
   unsigned int symbol_value;
   unsigned int priv_level;
   unsigned int secondary_def;
+  unsigned int is_comdat;
+  unsigned int is_common;
+  unsigned int dup_common;
 };
 
 /* Forward declarations.  */
@@ -1905,7 +1908,7 @@ setup_sections (abfd, file_hdr, current_offset)
   for (space_index = 0; space_index < file_hdr->space_total; space_index++)
     {
       struct space_dictionary_record space;
-      struct subspace_dictionary_record subspace, save_subspace;
+      struct som_subspace_dictionary_record subspace, save_subspace;
       unsigned int subspace_index;
       asection *space_asect;
       char *newname;
@@ -1973,7 +1976,7 @@ setup_sections (abfd, file_hdr, current_offset)
 
       /* Initialize save_subspace so we can reliably determine if this
         loop placed any useful values into it.  */
-      memset (&save_subspace, 0, sizeof (struct subspace_dictionary_record));
+      memset (&save_subspace, 0, sizeof (save_subspace));
 
       /* Loop over the rest of the subspaces, building up more sections.  */
       for (subspace_index = 0; subspace_index < space.subspace_quantity;
@@ -2004,7 +2007,10 @@ setup_sections (abfd, file_hdr, current_offset)
          if (! bfd_som_set_subsection_attributes (subspace_asect, space_asect,
                                                   subspace.access_control_bits,
                                                   subspace.sort_key,
-                                                  subspace.quadrant))
+                                                  subspace.quadrant,
+                                                  subspace.is_comdat,
+                                                  subspace.is_common,
+                                                  subspace.dup_common))
            goto error_return;
 
          /* Keep an easy mapping between subspaces and sections.
@@ -2050,9 +2056,10 @@ setup_sections (abfd, file_hdr, current_offset)
              break;
            }
 
-         if (subspace.dup_common || subspace.is_common)
-           subspace_asect->flags |= SEC_IS_COMMON;
-         else if (subspace.subspace_length > 0)
+         if (subspace.is_comdat || subspace.is_common || subspace.dup_common)
+           subspace_asect->flags |= SEC_LINK_ONCE;
+
+         if (subspace.subspace_length > 0)
            subspace_asect->flags |= SEC_HAS_CONTENTS;
 
          if (subspace.is_loadable)
@@ -2402,21 +2409,15 @@ som_prep_headers (abfd)
       else
        {
          /* Allocate space for the subspace dictionary.  */
-         amt = sizeof (struct subspace_dictionary_record);
+         amt = sizeof (struct som_subspace_dictionary_record);
          som_section_data (section)->subspace_dict =
-           (struct subspace_dictionary_record *) bfd_zalloc (abfd, amt);
+           (struct som_subspace_dictionary_record *) bfd_zalloc (abfd, amt);
          if (som_section_data (section)->subspace_dict == NULL)
            return FALSE;
 
          /* Set subspace attributes.  Basic stuff is done here, additional
             attributes are filled in later as more information becomes
             available.  */
-         if (section->flags & SEC_IS_COMMON)
-           {
-             som_section_data (section)->subspace_dict->dup_common = 1;
-             som_section_data (section)->subspace_dict->is_common = 1;
-           }
-
          if (section->flags & SEC_ALLOC)
            som_section_data (section)->subspace_dict->is_loadable = 1;
 
@@ -2439,6 +2440,12 @@ som_prep_headers (abfd)
            som_section_data (section)->copy_data->access_control_bits;
          som_section_data (section)->subspace_dict->quadrant =
            som_section_data (section)->copy_data->quadrant;
+         som_section_data (section)->subspace_dict->is_comdat =
+           som_section_data (section)->copy_data->is_comdat;
+         som_section_data (section)->subspace_dict->is_common =
+           som_section_data (section)->copy_data->is_common;
+         som_section_data (section)->subspace_dict->dup_common =
+           som_section_data (section)->copy_data->dup_common;
        }
     }
   return TRUE;
@@ -3474,7 +3481,8 @@ som_begin_writing (abfd)
   num_subspaces = som_count_subspaces (abfd);
   obj_som_file_hdr (abfd)->subspace_location = current_offset;
   obj_som_file_hdr (abfd)->subspace_total = num_subspaces;
-  current_offset += num_subspaces * sizeof (struct subspace_dictionary_record);
+  current_offset
+    += num_subspaces * sizeof (struct som_subspace_dictionary_record);
 
   /* Next is the string table for the space/subspace names.  We will
      build and write the string table on the fly.  At the same time
@@ -3849,7 +3857,7 @@ som_finish_writing (abfd)
          som_section_data (subsection)->subspace_dict->space_index = i;
 
          /* Dump the current subspace header.  */
-         amt = sizeof (struct subspace_dictionary_record);
+         amt = sizeof (struct som_subspace_dictionary_record);
          if (bfd_bwrite ((PTR) som_section_data (subsection)->subspace_dict,
                         amt, abfd) != amt)
            return FALSE;
@@ -3905,7 +3913,7 @@ som_finish_writing (abfd)
          som_section_data (subsection)->subspace_dict->space_index = i;
 
          /* Dump this subspace header.  */
-         amt = sizeof (struct subspace_dictionary_record);
+         amt = sizeof (struct som_subspace_dictionary_record);
          if (bfd_bwrite ((PTR) som_section_data (subsection)->subspace_dict,
                         amt, abfd) != amt)
            return FALSE;
@@ -4053,12 +4061,12 @@ som_bfd_derive_misc_symbol_info (abfd, sym, info)
     info->symbol_type = ST_DATA;
   else
     {
-      /* Common symbols must have scope SS_UNSAT and type
-        ST_STORAGE or the linker will choke.  */
+      /* For BFD style common, the linker will choke unless we set the
+        type and scope to ST_STORAGE and SS_UNSAT, respectively.  */
       if (bfd_is_com_section (sym->section))
        {
-         info->symbol_scope = SS_UNSAT;
          info->symbol_type = ST_STORAGE;
+         info->symbol_scope = SS_UNSAT;
        }
 
       /* It is possible to have a symbol without an associated
@@ -4097,9 +4105,6 @@ som_bfd_derive_misc_symbol_info (abfd, sym, info)
            info->symbol_type = ST_DATA;
        }
 
-      else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_UNKNOWN)
-       info->symbol_type = ST_DATA;
-
       /* From now on it's a very simple mapping.  */
       else if (som_symbol_data (sym)->som_type == SYMBOL_TYPE_ABSOLUTE)
        info->symbol_type = ST_ABSOLUTE;
@@ -4120,14 +4125,15 @@ som_bfd_derive_misc_symbol_info (abfd, sym, info)
   /* Now handle the symbol's scope.  Exported data which is not
      in the common section has scope SS_UNIVERSAL.  Note scope
      of common symbols was handled earlier!  */
-  if (bfd_is_und_section (sym->section))
+  if (bfd_is_com_section (sym->section))
+    ;
+  else if (bfd_is_und_section (sym->section))
     info->symbol_scope = SS_UNSAT;
-  else if (sym->flags & (BSF_EXPORT | BSF_WEAK)
-          && ! bfd_is_com_section (sym->section))
+  else if (sym->flags & (BSF_EXPORT | BSF_WEAK))
     info->symbol_scope = SS_UNIVERSAL;
   /* Anything else which is not in the common section has scope
      SS_LOCAL.  */
-  else if (! bfd_is_com_section (sym->section))
+  else
     info->symbol_scope = SS_LOCAL;
 
   /* Now set the symbol_info field.  It has no real meaning
@@ -4146,12 +4152,49 @@ som_bfd_derive_misc_symbol_info (abfd, sym, info)
   /* Set the symbol's value.  */
   info->symbol_value = sym->value + sym->section->vma;
 
-  /* The secondary_def field is for weak symbols.  */
+  /* The secondary_def field is for "weak" symbols.  */
   if (sym->flags & BSF_WEAK)
     info->secondary_def = TRUE;
   else
     info->secondary_def = FALSE;
 
+  /* The is_comdat, is_common and dup_common fields provide various
+     flavors of common.
+
+     For data symbols, setting IS_COMMON provides Fortran style common
+     (duplicate definitions and overlapped initialization).  Setting both
+     IS_COMMON and DUP_COMMON provides Cobol style common (duplicate
+     definitions as long as they are all the same length).  In a shared
+     link data symbols retain their IS_COMMON and DUP_COMMON flags.
+     An IS_COMDAT data symbol is similar to a IS_COMMON | DUP_COMMON
+     symbol except in that it loses its IS_COMDAT flag in a shared link.
+
+     For code symbols, IS_COMDAT and DUP_COMMON have effect.  Universal
+     DUP_COMMON code symbols are not exported from shared libraries.
+     IS_COMDAT symbols are exported but they lose their IS_COMDAT flag.
+
+     We take a simplified approach to setting the is_comdat, is_common
+     and dup_common flags in symbols based on the flag settings of their
+     subspace.  This avoids having to add directives like `.comdat' but
+     the linker behavior is probably undefined if there is more than one
+     universal symbol (comdat key sysmbol) in a subspace.
+
+     The behavior of these flags is not well documentmented, so there
+     may be bugs and some surprising interactions with other flags.  */
+  if (som_section_data (sym->section)
+      && som_section_data (sym->section)->subspace_dict
+      && info->symbol_scope == SS_UNIVERSAL
+      && (info->symbol_type == ST_ENTRY
+         || info->symbol_type == ST_CODE
+         || info->symbol_type == ST_DATA))
+    {
+      info->is_comdat
+       = som_section_data (sym->section)->subspace_dict->is_comdat;
+      info->is_common
+       = som_section_data (sym->section)->subspace_dict->is_common;
+      info->dup_common
+       = som_section_data (sym->section)->subspace_dict->dup_common;
+    }
 }
 
 /* Build and write, in one big chunk, the entire symbol table for
@@ -4197,6 +4240,9 @@ som_build_and_write_symbol_table (abfd)
       som_symtab[i].xleast = 3;
       som_symtab[i].symbol_value = info.symbol_value | info.priv_level;
       som_symtab[i].secondary_def = info.secondary_def;
+      som_symtab[i].is_comdat = info.is_comdat;
+      som_symtab[i].is_common = info.is_common;
+      som_symtab[i].dup_common = info.dup_common;
     }
 
   /* Everything is ready, seek to the right location and
@@ -5220,12 +5266,13 @@ bfd_som_set_section_attributes (section, defined, private, sort_key, spnum)
 
 bfd_boolean
 bfd_som_set_subsection_attributes (section, container, access,
-                                  sort_key, quadrant)
+                                  sort_key, quadrant, comdat,
+                                  common, dup_common)
      asection *section;
      asection *container;
      int access;
      unsigned int sort_key;
-     int quadrant;
+     int quadrant, comdat, common, dup_common;
 {
   /* Allocate memory to hold the magic information.  */
   if (som_section_data (section)->copy_data == NULL)
@@ -5241,6 +5288,9 @@ bfd_som_set_subsection_attributes (section, container, access,
   som_section_data (section)->copy_data->access_control_bits = access;
   som_section_data (section)->copy_data->quadrant = quadrant;
   som_section_data (section)->copy_data->container = container;
+  som_section_data (section)->copy_data->is_comdat = comdat;
+  som_section_data (section)->copy_data->is_common = common;
+  som_section_data (section)->copy_data->dup_common = dup_common;
   return TRUE;
 }
 
@@ -6044,7 +6094,7 @@ som_bfd_ar_write_symbol_stuff (abfd, nsyms, string_size, lst, elength)
          curr_lst_sym->initially_frozen = 0;
          curr_lst_sym->memory_resident = 0;
          curr_lst_sym->is_common = bfd_is_com_section (sym->symbol.section);
-         curr_lst_sym->dup_common = 0;
+         curr_lst_sym->dup_common = info.dup_common;
          curr_lst_sym->xleast = 3;
          curr_lst_sym->arg_reloc = info.arg_reloc;
          curr_lst_sym->name.n_strx = p - strings + 4;
@@ -6370,7 +6420,7 @@ const bfd_target som_vec = {
   (HAS_RELOC | EXEC_P |                /* object flags */
    HAS_LINENO | HAS_DEBUG |
    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED | DYNAMIC),
-  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS
+  (SEC_CODE | SEC_DATA | SEC_ROM | SEC_HAS_CONTENTS | SEC_LINK_ONCE
    | SEC_ALLOC | SEC_LOAD | SEC_RELOC),                /* section flags */
 
 /* leading_symbol_char: is the first char of a user symbol
index 537ddaa..3954855 100644 (file)
--- a/bfd/som.h
+++ b/bfd/som.h
@@ -27,7 +27,7 @@
 
 #include "libhppa.h"
 
-/* Enable PA2.0 if available */
+/* We want reloc.h to provide PA 2.0 defines.  */
 #define PA_2_0
 
 #include <a.out.h>
@@ -143,6 +143,35 @@ struct som_data_struct
     struct somdata a;
   };
 
+struct som_subspace_dictionary_record
+  {
+    int space_index;
+    unsigned int access_control_bits : 7;
+    unsigned int memory_resident : 1;
+    unsigned int dup_common : 1;
+    unsigned int is_common : 1;
+    unsigned int is_loadable : 1;
+    unsigned int quadrant : 2;
+    unsigned int initially_frozen : 1;
+    unsigned int is_first : 1;
+    unsigned int code_only : 1;
+    unsigned int sort_key : 8;
+    unsigned int replicate_init        : 1;
+    unsigned int continuation : 1;
+    unsigned int is_tspecific : 1;
+    unsigned int is_comdat : 1;
+    unsigned int reserved : 4;
+    int file_loc_init_value;
+    unsigned int initialization_length;
+    unsigned int subspace_start;
+    unsigned int subspace_length;
+    unsigned int reserved2 : 5;   
+    unsigned int alignment :27;
+    union name_pt name;
+    int fixup_request_index;
+    unsigned int fixup_request_quantity;
+  };
+
 /* Substructure of som_section_data_struct used to hold information
    which can't be represented by the generic BFD section structure,
    but which must be copied during objcopy or strip.  */
@@ -155,6 +184,9 @@ struct som_copyable_section_data_struct
     unsigned int is_defined : 1;
     unsigned int is_private : 1;
     unsigned int quadrant : 2;
+    unsigned int is_comdat : 1;
+    unsigned int is_common : 1;
+    unsigned int dup_common : 1;
 
     /* For subspaces, this points to the section which represents the
        space in which the subspace is contained.  For spaces it points
@@ -184,7 +216,7 @@ struct som_section_data_struct
     unsigned int reloc_size;
     char *reloc_stream;
     struct space_dictionary_record *space_dict;
-    struct subspace_dictionary_record *subspace_dict;
+    struct som_subspace_dictionary_record *subspace_dict;
   };
 
 #define somdata(bfd)                   ((bfd)->tdata.som_data->a)
@@ -231,7 +263,7 @@ struct som_section_data_struct
 bfd_boolean bfd_som_set_section_attributes
   PARAMS ((asection *, int, int, unsigned int, int));
 bfd_boolean bfd_som_set_subsection_attributes
-  PARAMS ((asection *, asection *, int, unsigned int, int));
+  PARAMS ((asection *, asection *, int, unsigned int, int, int, int, int));
 void bfd_som_set_symbol_type PARAMS ((asymbol *, unsigned int));
 bfd_boolean bfd_som_attach_aux_hdr PARAMS ((bfd *, int, char *));
 int ** hppa_som_gen_reloc_type
index 08a4750..23eee16 100644 (file)
@@ -1,3 +1,18 @@
+2004-04-28  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
+
+       * config/obj-som.c (obj_som_init_stab_section): Add new arguments in
+       call to obj_set_subsection_attributes.
+       (obj_som_init_stab_section): Likewise.
+       * config/tc-hppa.c (default_subspace_dict): Add comdat field.
+       (pa_def_subspaces): Provide comdat default.
+       (pa_subspace): Handle new "comdat" parameter.  Set SEC_LINK_ONCE and
+       not SEC_IS_COMMON if section is comdat, common or dup_common.  Update
+       calls to create_new_subspace and update_subspace to pass comdat flag.
+       (create_new_subspace, update_subspace): Add new comdat argument.  Use
+       it in calls to obj_set_subsection_attributes.
+       * doc/c-hppa.texi (.subspa, .nsubspa): Document new comdat parameter
+       and use of comdat, common and dup_comm parameters.
+
 2004-04-26  H.J. Lu  <hongjiu.lu@intel.com>
 
        * config/obj-elf.c (obj_elf_change_section): Check if the old
index 454042a..a736c96 100644 (file)
@@ -248,7 +248,7 @@ obj_som_init_stab_section (seg)
      (just created above).  Also set some attributes which BFD does
      not understand.  In particular, access bits, sort keys, and load
      quadrant.  */
-  obj_set_subsection_attributes (seg, space, 0x1f, 73, 0);
+  obj_set_subsection_attributes (seg, space, 0x1f, 73, 0, 0, 0, 0);
   bfd_set_section_alignment (stdoutput, seg, 2);
 
   /* Make some space for the first special stab entry and zero the memory.
@@ -271,7 +271,7 @@ obj_som_init_stab_section (seg)
      not understand.  In particular, access bits, sort keys, and load
      quadrant.  */
   seg = bfd_get_section_by_name (stdoutput, "$GDB_STRINGS$");
-  obj_set_subsection_attributes (seg, space, 0x1f, 72, 0);
+  obj_set_subsection_attributes (seg, space, 0x1f, 72, 0, 0, 0, 0);
   bfd_set_section_alignment (stdoutput, seg, 2);
 
   subseg_set (saved_seg, saved_subseg);
index 77563a9..72abe1d 100644 (file)
@@ -363,6 +363,9 @@ struct default_subspace_dict
     /* Nonzero if this subspace contains only code.  */
     char code_only;
 
+    /* Nonzero if this is a comdat subspace.  */
+    char comdat;
+
     /* Nonzero if this is a common subspace.  */
     char common;
 
@@ -555,13 +558,13 @@ static sd_chain_struct *create_new_space PARAMS ((char *, int, int,
                                                  asection *, int));
 static ssd_chain_struct *create_new_subspace PARAMS ((sd_chain_struct *,
                                                      char *, int, int,
-                                                     int, int, int,
+                                                     int, int, int, int,
                                                      int, int, int, int,
                                                      int, asection *));
 static ssd_chain_struct *update_subspace PARAMS ((sd_chain_struct *,
                                                  char *, int, int, int,
                                                  int, int, int, int,
-                                                 int, int, int,
+                                                 int, int, int, int,
                                                  asection *));
 static sd_chain_struct *is_defined_space PARAMS ((char *));
 static ssd_chain_struct *is_defined_subspace PARAMS ((char *));
@@ -1117,12 +1120,12 @@ static const struct selector_entry selector_table[] =
 
 static struct default_subspace_dict pa_def_subspaces[] =
 {
-  {"$CODE$", 1, 1, 1, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE},
-  {"$DATA$", 1, 1, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, SUBSEG_DATA},
-  {"$LIT$", 1, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT},
-  {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, SUBSEG_MILLI},
-  {"$BSS$", 1, 1, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, SUBSEG_BSS},
-  {NULL, 0, 1, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0}
+  {"$CODE$", 1, 1, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE},
+  {"$DATA$", 1, 1, 0, 0, 0, 0, 0, 24, 0x1f, 1, 8, 1, 1, SUBSEG_DATA},
+  {"$LIT$", 1, 1, 0, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT},
+  {"$MILLICODE$", 1, 1, 0, 0, 0, 0, 0, 8, 0x2c, 0, 8, 0, 0, SUBSEG_MILLI},
+  {"$BSS$", 1, 1, 0, 0, 0, 0, 1, 80, 0x1f, 1, 8, 1, 1, SUBSEG_BSS},
+  {NULL, 0, 1, 0, 0, 0, 0, 0, 255, 0x1f, 0, 4, 0, 0, 0}
 };
 
 static struct default_space_dict pa_def_spaces[] =
@@ -7454,7 +7457,7 @@ pa_subspace (create_new)
      int create_new;
 {
   char *name, *ss_name, c;
-  char loadable, code_only, common, dup_common, zero, sort;
+  char loadable, code_only, comdat, common, dup_common, zero, sort;
   int i, access, space_index, alignment, quadrant, applicable, flags;
   sd_chain_struct *space;
   ssd_chain_struct *ssd;
@@ -7480,6 +7483,7 @@ pa_subspace (create_new)
       sort = 0;
       access = 0x7f;
       loadable = 1;
+      comdat = 0;
       common = 0;
       dup_common = 0;
       code_only = 0;
@@ -7514,6 +7518,7 @@ pa_subspace (create_new)
              if (strcasecmp (pa_def_subspaces[i].name, ss_name) == 0)
                {
                  loadable = pa_def_subspaces[i].loadable;
+                 comdat = pa_def_subspaces[i].comdat;
                  common = pa_def_subspaces[i].common;
                  dup_common = pa_def_subspaces[i].dup_common;
                  code_only = pa_def_subspaces[i].code_only;
@@ -7577,6 +7582,11 @@ pa_subspace (create_new)
                  *input_line_pointer = c;
                  loadable = 0;
                }
+             else if ((strncasecmp (name, "comdat", 6) == 0))
+               {
+                 *input_line_pointer = c;
+                 comdat = 1;
+               }
              else if ((strncasecmp (name, "common", 6) == 0))
                {
                  *input_line_pointer = c;
@@ -7609,8 +7619,17 @@ pa_subspace (create_new)
        flags |= (SEC_ALLOC | SEC_LOAD);
       if (code_only)
        flags |= SEC_CODE;
-      if (common || dup_common)
-       flags |= SEC_IS_COMMON;
+
+      /* These flags are used to implement various flavors of initialized
+        common.  The SOM linker discards duplicate subspaces when they
+        have the same "key" symbol name.  This support is more like
+        GNU linkonce than BFD common.  Further, pc-relative relocations
+        are converted to section relative relocations in BFD common
+        sections.  This complicates the handling of relocations in
+        common sections containing text and isn't currently supported
+        correctly in the SOM BFD backend.  */
+      if (comdat || common || dup_common)
+       flags |= SEC_LINK_ONCE;
 
       flags |= SEC_RELOC | SEC_HAS_CONTENTS;
 
@@ -7652,16 +7671,16 @@ pa_subspace (create_new)
       if (ssd)
 
        current_subspace = update_subspace (space, ss_name, loadable,
-                                           code_only, common, dup_common,
-                                           sort, zero, access, space_index,
-                                           alignment, quadrant,
+                                           code_only, comdat, common,
+                                           dup_common, sort, zero, access,
+                                           space_index, alignment, quadrant,
                                            section);
       else
        current_subspace = create_new_subspace (space, ss_name, loadable,
-                                               code_only, common,
+                                               code_only, comdat, common,
                                                dup_common, zero, sort,
                                                access, space_index,
-                                             alignment, quadrant, section);
+                                               alignment, quadrant, section);
 
       demand_empty_rest_of_line ();
       current_subspace->ssd_seg = section;
@@ -7782,6 +7801,7 @@ pa_spaces_begin ()
       create_new_subspace (space, name,
                           pa_def_subspaces[i].loadable,
                           pa_def_subspaces[i].code_only,
+                          pa_def_subspaces[i].comdat,
                           pa_def_subspaces[i].common,
                           pa_def_subspaces[i].dup_common,
                           pa_def_subspaces[i].zero,
@@ -7883,12 +7903,12 @@ create_new_space (name, spnum, loadable, defined, private,
    order as defined by the SORT entries.  */
 
 static ssd_chain_struct *
-create_new_subspace (space, name, loadable, code_only, common,
+create_new_subspace (space, name, loadable, code_only, comdat, common,
                     dup_common, is_zero, sort, access, space_index,
                     alignment, quadrant, seg)
      sd_chain_struct *space;
      char *name;
-     int loadable, code_only, common, dup_common, is_zero;
+     int loadable, code_only, comdat, common, dup_common, is_zero;
      int sort;
      int access;
      int space_index;
@@ -7945,8 +7965,8 @@ create_new_subspace (space, name, loadable, code_only, common,
     }
 
 #ifdef obj_set_subsection_attributes
-  obj_set_subsection_attributes (seg, space->sd_seg, access,
-                                sort, quadrant);
+  obj_set_subsection_attributes (seg, space->sd_seg, access, sort,
+                                quadrant, comdat, common, dup_common);
 #endif
 
   return chain_entry;
@@ -7956,12 +7976,13 @@ create_new_subspace (space, name, loadable, code_only, common,
    various arguments.   Return the modified subspace chain entry.  */
 
 static ssd_chain_struct *
-update_subspace (space, name, loadable, code_only, common, dup_common, sort,
-                zero, access, space_index, alignment, quadrant, section)
+update_subspace (space, name, loadable, code_only, comdat, common, dup_common,
+                sort, zero, access, space_index, alignment, quadrant, section)
      sd_chain_struct *space;
      char *name;
      int loadable;
      int code_only;
+     int comdat;
      int common;
      int dup_common;
      int zero;
@@ -7977,8 +7998,8 @@ update_subspace (space, name, loadable, code_only, common, dup_common, sort,
   chain_entry = is_defined_subspace (name);
 
 #ifdef obj_set_subsection_attributes
-  obj_set_subsection_attributes (section, space->sd_seg, access,
-                                sort, quadrant);
+  obj_set_subsection_attributes (section, space->sd_seg, access, sort,
+                                quadrant, comdat, common, dup_common);
 #endif
 
   return chain_entry;
index 7e9ea30..9970188 100644 (file)
@@ -245,14 +245,51 @@ identified by keywords.  The keywords recognized are @samp{quad=@var{expr}}
 beginning of this subsection; a power of two), @samp{access=@var{expr}} (value
 for ``access rights'' field), @samp{sort=@var{expr}} (sorting order for this
 subspace in link), @samp{code_only} (subsection contains only code),
-@samp{unloadable} (subsection cannot be loaded into memory), @samp{common}
-(subsection is common block), @samp{dup_comm} (initialized data may have
-duplicate names), or @samp{zero} (subsection is all zeros, do not write in
-object file).
+@samp{unloadable} (subsection cannot be loaded into memory), @samp{comdat}
+(subsection is comdat), @samp{common} (subsection is common block),
+@samp{dup_comm} (subsection may have duplicate names), or @samp{zero}
+(subsection is all zeros, do not write in object file).
 
 @code{.nsubspa} always creates a new subspace with the given name, even
 if one with the same name already exists.
 
+@samp{comdat}, @samp{common} and @samp{dup_comm} can be used to implement
+various flavors of one-only support when using the SOM linker.  The SOM
+linker only supports specific combinations of these flags.  The details
+are not documented.  A brief description is provided here.
+
+@samp{comdat} provides a form of linkonce support.  It is useful for
+both code and data subspaces.  A @samp{comdat} subspace has a key symbol
+marked by the @samp{is_comdat} flag or @samp{ST_COMDAT}.  Only the first
+subspace for any given key is selected.  The key symbol becomes universal
+in shared links.  This is similar to the behavior of @samp{secondary_def}
+symbols.
+
+@samp{common} provides Fortran named common support.  It is only useful
+for data subspaces.  Symbols with the flag @samp{is_common} retain this
+flag in shared links.  Referencing a @samp{is_common} symbol in a shared
+library from outside the library doesn't work.  Thus, @samp{is_common}
+symbols must be output whenever they are needed.
+
+@samp{common} and @samp{dup_comm} together provide Cobol common support.
+The subspaces in this case must all be the same length.  Otherwise, this
+support is similar to the Fortran common support.
+
+@samp{dup_comm} by itself provides a type of one-only support for code.
+Only the first @samp{dup_comm} subspace is selected.  There is a rather
+complex algorithm to compare subspaces.  Code symbols marked with the
+@samp{dup_common} flag are hidden.  This support was intended for "C++
+duplicate inlines".
+
+A simplified technique is used to mark the flags of symbols based on
+the flags of their subspace.  A symbol with the scope SS_UNIVERSAL and
+type ST_ENTRY, ST_CODE or ST_DATA is marked with the corresponding
+settings of @samp{comdat}, @samp{common} and @samp{dup_comm} from the
+subspace, respectively.  This avoids having to introduce additional
+directives to mark these symbols.  The HP assembler sets @samp{is_common}
+from @samp{common}.  However, it doesn't set the @samp{dup_common} from
+@samp{dup_comm}.  It doesn't have @samp{comdat} support.
+
 @item .version "@var{str}"
 Write @var{str} as version identifier in object code.
 @end table