From 351e2b5aa7a71258e6b682ac1a3228964de8d22c Mon Sep 17 00:00:00 2001 From: Dave Anglin Date: Wed, 28 Apr 2004 18:02:49 +0000 Subject: [PATCH] * 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. --- bfd/ChangeLog | 30 ++++++++++++ bfd/som.c | 114 +++++++++++++++++++++++++++++++------------ bfd/som.h | 38 +++++++++++++-- gas/ChangeLog | 15 ++++++ gas/config/obj-som.c | 4 +- gas/config/tc-hppa.c | 69 +++++++++++++++++--------- gas/doc/c-hppa.texi | 45 +++++++++++++++-- 7 files changed, 250 insertions(+), 65 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9962fb5377b..8fbe78e45be 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,33 @@ +2004-04-28 John David Anglin + + * 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 * elf32-xtensa.c (xtensa_read_table_entries): Use section _cooked_size diff --git a/bfd/som.c b/bfd/som.c index 1d2d99e3129..6f053913c27 100644 --- 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 diff --git a/bfd/som.h b/bfd/som.h index 537ddaad1f0..3954855b614 100644 --- 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 @@ -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 diff --git a/gas/ChangeLog b/gas/ChangeLog index 08a47509a09..23eee168529 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,18 @@ +2004-04-28 John David Anglin + + * 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 * config/obj-elf.c (obj_elf_change_section): Check if the old diff --git a/gas/config/obj-som.c b/gas/config/obj-som.c index 454042a4f41..a736c9658ea 100644 --- a/gas/config/obj-som.c +++ b/gas/config/obj-som.c @@ -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); diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c index 77563a99bee..72abe1dedb5 100644 --- a/gas/config/tc-hppa.c +++ b/gas/config/tc-hppa.c @@ -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; diff --git a/gas/doc/c-hppa.texi b/gas/doc/c-hppa.texi index 7e9ea3082da..9970188ab4f 100644 --- a/gas/doc/c-hppa.texi +++ b/gas/doc/c-hppa.texi @@ -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 -- 2.30.2