This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed] SOM linkonce/common support


The enclosed patch is mainly for use with GCC and hpux 10.20 which doesn't
support secondary_def (weak) symbols.  It adds support for various flavors
of common on the SOM target.

I have tested the patch with a modified version of gcc 3.3.4.  Using
the COMDAT support below, I implemented one-only support in gcc.  This
provides implicit template instantiation and vastly simplified vtable
and typeinfo node handling.  I was then able to build working versions
of the C++ applications groff and lyx.  Previously, this wasn't possible.

Installed to the trunk about 10 years too late.

Dave
-- 
J. David Anglin                                  dave.anglin@nrc-cnrc.gc.ca
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)

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.

	* 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.

Index: bfd/som.c
===================================================================
RCS file: /cvs/src/src/bfd/som.c,v
retrieving revision 1.39
diff -u -3 -p -r1.39 som.c
--- bfd/som.c	22 Apr 2004 23:17:07 -0000	1.39
+++ bfd/som.c	26 Apr 2004 04:18:46 -0000
@@ -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_
   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_
 
       /* 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_
 	  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_
 	      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, s
     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, s
 	    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, s
   /* 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, s
   /* 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,
 
 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 (secti
   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, nsy
 	  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: bfd/som.h
===================================================================
RCS file: /cvs/src/src/bfd/som.h,v
retrieving revision 1.9
diff -u -3 -p -r1.9 som.h
--- bfd/som.h	30 Nov 2003 18:40:41 -0000	1.9
+++ bfd/som.h	26 Apr 2004 04:18:46 -0000
@@ -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: gas/config/obj-som.c
===================================================================
RCS file: /cvs/src/src/gas/config/obj-som.c,v
retrieving revision 1.7
diff -u -3 -p -r1.7 obj-som.c
--- gas/config/obj-som.c	20 Nov 2003 00:01:55 -0000	1.7
+++ gas/config/obj-som.c	26 Apr 2004 04:18:46 -0000
@@ -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: gas/config/tc-hppa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-hppa.c,v
retrieving revision 1.110
diff -u -3 -p -r1.110 tc-hppa.c
--- gas/config/tc-hppa.c	19 Mar 2004 19:19:53 -0000	1.110
+++ gas/config/tc-hppa.c	26 Apr 2004 04:18:47 -0000
@@ -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
 						  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 selec
 
 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,
    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, loadab
     }
 
 #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, loadab
    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, 
   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: gas/doc/c-hppa.texi
===================================================================
RCS file: /cvs/src/src/gas/doc/c-hppa.texi,v
retrieving revision 1.3
diff -u -3 -p -r1.3 c-hppa.texi
--- gas/doc/c-hppa.texi	7 Mar 2004 15:00:16 -0000	1.3
+++ gas/doc/c-hppa.texi	26 Apr 2004 04:18:47 -0000
@@ -245,13 +245,50 @@ identified by keywords.  The keywords re
 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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]