From 74869ac7a4dcde1530155889456cbaa37f87b60c Mon Sep 17 00:00:00 2001 From: Bob Wilson Date: Fri, 25 Aug 2006 00:08:55 +0000 Subject: [PATCH] bfd/ * elf32-xtensa.c (xtensa_get_property_section_name): Delete. (xtensa_get_property_section): New. (xtensa_read_table_entries): Use xtensa_get_property_section. (relax_property_section, xtensa_get_property_predef_flags): Handle group name suffixes in property section names. (match_section_group): New. gas/ * config/tc-xtensa.c (FINI_LITERAL_SECTION_NAME): Delete. (INIT_LITERAL_SECTION_NAME): Delete. (lit_state struct): Remove segment names, init_lit_seg, and fini_lit_seg. Add lit_prefix and current_text_seg. (init_literal_head_h, init_literal_head): Delete. (fini_literal_head_h, fini_literal_head): Delete. (xtensa_begin_directive): Move argument parsing to xtensa_literal_prefix function. (xtensa_end_directive): Deallocate lit_prefix field of lit_state. (xtensa_literal_prefix): Parse the directive argument here and record it in the lit_prefix field. Remove code to derive literal section names. (linkonce_len): New. (get_is_linkonce_section): Use linkonce_len. Check for any ".gnu.linkonce.*" section, not just text sections. (md_begin): Remove initialization of deleted lit_state fields. (xtensa_reorder_segments, xtensa_post_relax_hook): Remove references to init_literal_head and fini_literal_head. (xtensa_move_literals): Likewise. Skip literals for .init and .fini when traversing literal_head list. (match_section_group): New. (cache_literal_section): Rewrite to determine the literal section name on the fly, create the section and return it. (xtensa_switch_to_literal_fragment): Adjust for cache_literal_section. (xtensa_switch_to_non_abs_literal_fragment): Likewise. (xtensa_create_property_segments, xtensa_create_xproperty_segments): Use xtensa_get_property_section from bfd. (retrieve_xtensa_section): Delete. * doc/c-xtensa.texi (Xtensa Options): Fix --text-section-literals description to refer to plural literal sections and add xref to the Literal Directive section. (Literal Directive): Describe new rules for deriving literal section names. Add footnote for special case of .init/.fini with --text-section-literals. (Literal Prefix Directive): Replace old naming rules with xref to the Literal Directive section. ld/ * emulparams/elf32xtensa.sh (.xt.prop): Add .xt.prop.*. * scripttempl/elfxtensa.sc (.text): Add .literal.*. --- bfd/ChangeLog | 9 + bfd/elf32-xtensa.c | 76 ++++++-- gas/ChangeLog | 39 ++++ gas/config/tc-xtensa.c | 365 ++++++++++++++++------------------- gas/doc/c-xtensa.texi | 93 +++++---- ld/ChangeLog | 5 + ld/emulparams/elf32xtensa.sh | 2 +- ld/scripttempl/elfxtensa.sc | 2 +- 8 files changed, 342 insertions(+), 249 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4bfa63f1363..e032bb60c2f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +2006-08-24 Bob Wilson + + * elf32-xtensa.c (xtensa_get_property_section_name): Delete. + (xtensa_get_property_section): New. + (xtensa_read_table_entries): Use xtensa_get_property_section. + (relax_property_section, xtensa_get_property_predef_flags): Handle + group name suffixes in property section names. + (match_section_group): New. + 2006-08-23 Frediano Ziglio * archive.c (hpux_uid_gid_encode): Fix thinko decrementing "cnt" diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index 5efdcbac962..88365ddd32a 100644 --- a/bfd/elf32-xtensa.c +++ b/bfd/elf32-xtensa.c @@ -106,7 +106,7 @@ static bfd_boolean xtensa_is_property_section (asection *); static bfd_boolean xtensa_is_littable_section (asection *); static int internal_reloc_compare (const void *, const void *); static int internal_reloc_matches (const void *, const void *); -extern char *xtensa_get_property_section_name (asection *, const char *); +extern asection *xtensa_get_property_section (asection *, const char *); static flagword xtensa_get_property_predef_flags (asection *); /* Other functions called directly by the linker. */ @@ -571,7 +571,6 @@ xtensa_read_table_entries (bfd *abfd, bfd_boolean output_addr) { asection *table_section; - char *table_section_name; bfd_size_type table_size = 0; bfd_byte *table_data; property_table_entry *blocks; @@ -590,9 +589,7 @@ xtensa_read_table_entries (bfd *abfd, return 0; } - table_section_name = xtensa_get_property_section_name (section, sec_name); - table_section = bfd_get_section_by_name (abfd, table_section_name); - free (table_section_name); + table_section = xtensa_get_property_section (section, sec_name); if (table_section) table_size = table_section->size; @@ -8857,7 +8854,8 @@ relax_property_section (bfd *abfd, } is_full_prop_section = - ((strcmp (sec->name, XTENSA_PROP_SEC_NAME) == 0) + ((strncmp (sec->name, XTENSA_PROP_SEC_NAME, + sizeof (XTENSA_PROP_SEC_NAME) - 1) == 0) || (strncmp (sec->name, ".gnu.linkonce.prop.", sizeof ".gnu.linkonce.prop." - 1) == 0)); @@ -9593,13 +9591,42 @@ internal_reloc_matches (const void *ap, const void *bp) } -char * -xtensa_get_property_section_name (asection *sec, const char *base_name) +/* Predicate function used to look up a section in a particular group. */ + +static bfd_boolean +match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf) +{ + const char *gname = inf; + const char *group_name = elf_group_name (sec); + + return (group_name == gname + || (group_name != NULL + && gname != NULL + && strcmp (group_name, gname) == 0)); +} + + +asection * +xtensa_get_property_section (asection *sec, const char *base_name) { - if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0) + const char *suffix, *group_name; + char *prop_sec_name; + asection *prop_sec; + + group_name = elf_group_name (sec); + if (group_name) + { + suffix = strrchr (sec->name, '.'); + if (suffix == sec->name) + suffix = 0; + prop_sec_name = (char *) bfd_malloc (strlen (base_name) + 1 + + (suffix ? strlen (suffix) : 0)); + strcpy (prop_sec_name, base_name); + if (suffix) + strcat (prop_sec_name, suffix); + } + else if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0) { - char *prop_sec_name; - const char *suffix; char *linkonce_kind = 0; if (strcmp (base_name, XTENSA_INSN_SEC_NAME) == 0) @@ -9622,18 +9649,39 @@ xtensa_get_property_section_name (asection *sec, const char *base_name) if (strncmp (suffix, "t.", 2) == 0 && linkonce_kind[1] == '.') suffix += 2; strcat (prop_sec_name + linkonce_len, suffix); + } + else + prop_sec_name = strdup (base_name); + + /* Check if the section already exists. */ + prop_sec = bfd_get_section_by_name_if (sec->owner, prop_sec_name, + match_section_group, + (void *) group_name); + /* If not, create it. */ + if (! prop_sec) + { + flagword flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY); + flags |= (bfd_get_section_flags (sec->owner, sec) + & (SEC_LINK_ONCE | SEC_LINK_DUPLICATES)); + + prop_sec = bfd_make_section_anyway_with_flags + (sec->owner, strdup (prop_sec_name), flags); + if (! prop_sec) + return 0; - return prop_sec_name; + elf_group_name (prop_sec) = group_name; } - return strdup (base_name); + free (prop_sec_name); + return prop_sec; } flagword xtensa_get_property_predef_flags (asection *sec) { - if (strcmp (sec->name, XTENSA_INSN_SEC_NAME) == 0 + if (strncmp (sec->name, XTENSA_INSN_SEC_NAME, + sizeof (XTENSA_INSN_SEC_NAME) - 1) == 0 || strncmp (sec->name, ".gnu.linkonce.x.", sizeof ".gnu.linkonce.x." - 1) == 0) return (XTENSA_PROP_INSN diff --git a/gas/ChangeLog b/gas/ChangeLog index ca8e0a5ecfa..2c187a9e3d9 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,42 @@ +2006-08-24 Bob Wilson + + * config/tc-xtensa.c (FINI_LITERAL_SECTION_NAME): Delete. + (INIT_LITERAL_SECTION_NAME): Delete. + (lit_state struct): Remove segment names, init_lit_seg, and + fini_lit_seg. Add lit_prefix and current_text_seg. + (init_literal_head_h, init_literal_head): Delete. + (fini_literal_head_h, fini_literal_head): Delete. + (xtensa_begin_directive): Move argument parsing to + xtensa_literal_prefix function. + (xtensa_end_directive): Deallocate lit_prefix field of lit_state. + (xtensa_literal_prefix): Parse the directive argument here and + record it in the lit_prefix field. Remove code to derive literal + section names. + (linkonce_len): New. + (get_is_linkonce_section): Use linkonce_len. Check for any + ".gnu.linkonce.*" section, not just text sections. + (md_begin): Remove initialization of deleted lit_state fields. + (xtensa_reorder_segments, xtensa_post_relax_hook): Remove references + to init_literal_head and fini_literal_head. + (xtensa_move_literals): Likewise. Skip literals for .init and .fini + when traversing literal_head list. + (match_section_group): New. + (cache_literal_section): Rewrite to determine the literal section + name on the fly, create the section and return it. + (xtensa_switch_to_literal_fragment): Adjust for cache_literal_section. + (xtensa_switch_to_non_abs_literal_fragment): Likewise. + (xtensa_create_property_segments, xtensa_create_xproperty_segments): + Use xtensa_get_property_section from bfd. + (retrieve_xtensa_section): Delete. + * doc/c-xtensa.texi (Xtensa Options): Fix --text-section-literals + description to refer to plural literal sections and add xref to + the Literal Directive section. + (Literal Directive): Describe new rules for deriving literal section + names. Add footnote for special case of .init/.fini with + --text-section-literals. + (Literal Prefix Directive): Replace old naming rules with xref to the + Literal Directive section. + 2006-08-21 Joseph Myers * config/tc-arm.c (s_arm_unwind_save_mmxwr): Correct condition for diff --git a/gas/config/tc-xtensa.c b/gas/config/tc-xtensa.c index 26b389eb796..476b2d26d71 100644 --- a/gas/config/tc-xtensa.c +++ b/gas/config/tc-xtensa.c @@ -95,33 +95,32 @@ static bfd_boolean past_xtensa_end = FALSE; #define LITERAL_SECTION_NAME xtensa_section_rename (".literal") #define LIT4_SECTION_NAME xtensa_section_rename (".lit4") -#define FINI_SECTION_NAME xtensa_section_rename (".fini") #define INIT_SECTION_NAME xtensa_section_rename (".init") -#define FINI_LITERAL_SECTION_NAME xtensa_section_rename (".fini.literal") -#define INIT_LITERAL_SECTION_NAME xtensa_section_rename (".init.literal") +#define FINI_SECTION_NAME xtensa_section_rename (".fini") /* This type is used for the directive_stack to keep track of the - state of the literal collection pools. */ + state of the literal collection pools. If lit_prefix is set, it is + used to determine the literal section names; otherwise, the literal + sections are determined based on the current text section. The + lit_seg and lit4_seg fields cache these literal sections, with the + current_text_seg field used a tag to indicate whether the cached + values are valid. */ typedef struct lit_state_struct { - const char *lit_seg_name; - const char *lit4_seg_name; - const char *init_lit_seg_name; - const char *fini_lit_seg_name; + char *lit_prefix; + segT current_text_seg; segT lit_seg; segT lit4_seg; - segT init_lit_seg; - segT fini_lit_seg; } lit_state; static lit_state default_lit_sections; -/* We keep lists of literal segments. The seg_list type is the node - for such a list. The *_literal_head locals are the heads of the - various lists. All of these lists have a dummy node at the start. */ +/* We keep a list of literal segments. The seg_list type is the node + for this list. The literal_head pointer is the head of the list, + with the literal_head_h dummy node at the start. */ typedef struct seg_list_struct { @@ -131,10 +130,6 @@ typedef struct seg_list_struct static seg_list literal_head_h; static seg_list *literal_head = &literal_head_h; -static seg_list init_literal_head_h; -static seg_list *init_literal_head = &init_literal_head_h; -static seg_list fini_literal_head_h; -static seg_list *fini_literal_head = &fini_literal_head_h; /* Lists of symbols. We keep a list of symbols that label the current @@ -414,7 +409,7 @@ bfd_boolean directive_state[] = static void xtensa_begin_directive (int); static void xtensa_end_directive (int); -static void xtensa_literal_prefix (char const *, int); +static void xtensa_literal_prefix (void); static void xtensa_literal_position (int); static void xtensa_literal_pseudo (int); static void xtensa_frequency_pseudo (int); @@ -463,12 +458,11 @@ static void xtensa_switch_to_literal_fragment (emit_state *); static void xtensa_switch_to_non_abs_literal_fragment (emit_state *); static void xtensa_switch_section_emit_state (emit_state *, segT, subsegT); static void xtensa_restore_emit_state (emit_state *); -static void cache_literal_section - (seg_list *, const char *, segT *, bfd_boolean); +static segT cache_literal_section (bfd_boolean); /* Import from elf32-xtensa.c in BFD library. */ -extern char *xtensa_get_property_section_name (asection *, const char *); +extern asection *xtensa_get_property_section (asection *, const char *); /* op_placement_info functions. */ @@ -1173,7 +1167,6 @@ xtensa_begin_directive (int ignore ATTRIBUTE_UNUSED) directiveE directive; bfd_boolean negated; emit_state *state; - int len; lit_state *ls; get_directive (&directive, &negated); @@ -1220,20 +1213,10 @@ xtensa_begin_directive (int ignore ATTRIBUTE_UNUSED) assert (ls); *ls = default_lit_sections; - directive_push (directive_literal_prefix, negated, ls); - /* Parse the new prefix from the input_line_pointer. */ - SKIP_WHITESPACE (); - len = strspn (input_line_pointer, - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz_/0123456789.$"); - /* Process the new prefix. */ - xtensa_literal_prefix (input_line_pointer, len); - - /* Skip the name in the input line. */ - input_line_pointer += len; + xtensa_literal_prefix (); break; case directive_freeregs: @@ -1353,10 +1336,10 @@ xtensa_end_directive (int ignore ATTRIBUTE_UNUSED) /* Restore the default collection sections from saved state. */ s = (lit_state *) state; assert (s); - default_lit_sections = *s; - /* free the state storage */ + /* Free the state storage. */ + free (s->lit_prefix); free (s); break; @@ -1463,62 +1446,31 @@ xtensa_literal_pseudo (int ignored ATTRIBUTE_UNUSED) static void -xtensa_literal_prefix (char const *start, int len) +xtensa_literal_prefix (void) { - char *name, *linkonce_suffix; - char *newname, *newname4; - size_t linkonce_len; + char *name; + int len; + + /* Parse the new prefix from the input_line_pointer. */ + SKIP_WHITESPACE (); + len = strspn (input_line_pointer, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz_/0123456789.$"); /* Get a null-terminated copy of the name. */ name = xmalloc (len + 1); assert (name); - - strncpy (name, start, len); + strncpy (name, input_line_pointer, len); name[len] = 0; - /* Allocate the sections (interesting note: the memory pointing to - the name is actually used for the name by the new section). */ - - newname = xmalloc (len + strlen (".literal") + 1); - newname4 = xmalloc (len + strlen (".lit4") + 1); - - linkonce_len = sizeof (".gnu.linkonce.") - 1; - if (strncmp (name, ".gnu.linkonce.", linkonce_len) == 0 - && (linkonce_suffix = strchr (name + linkonce_len, '.')) != 0) - { - strcpy (newname, ".gnu.linkonce.literal"); - strcpy (newname4, ".gnu.linkonce.lit4"); - - strcat (newname, linkonce_suffix); - strcat (newname4, linkonce_suffix); - } - else - { - int suffix_pos = len; - - /* If the section name ends with ".text", then replace that suffix - instead of appending an additional suffix. */ - if (len >= 5 && strcmp (name + len - 5, ".text") == 0) - suffix_pos -= 5; + /* Skip the name in the input line. */ + input_line_pointer += len; - strcpy (newname, name); - strcpy (newname4, name); + default_lit_sections.lit_prefix = name; - strcpy (newname + suffix_pos, ".literal"); - strcpy (newname4 + suffix_pos, ".lit4"); - } - - /* Note that cache_literal_section does not create a segment if - it already exists. */ + /* Clear cached literal sections, since the prefix has changed. */ default_lit_sections.lit_seg = NULL; default_lit_sections.lit4_seg = NULL; - - /* Canonicalizing section names allows renaming literal - sections to occur correctly. */ - default_lit_sections.lit_seg_name = tc_canonicalize_symbol_name (newname); - default_lit_sections.lit4_seg_name = tc_canonicalize_symbol_name (newname4); - - free (name); } @@ -3921,7 +3873,9 @@ xg_expand_assembly_insn (IStack *istack, TInsn *orig_insn) /* Return TRUE if the section flags are marked linkonce - or the name is .gnu.linkonce*. */ + or the name is .gnu.linkonce.*. */ + +static int linkonce_len = sizeof (".gnu.linkonce.") - 1; static bfd_boolean get_is_linkonce_section (bfd *abfd ATTRIBUTE_UNUSED, segT sec) @@ -3932,13 +3886,10 @@ get_is_linkonce_section (bfd *abfd ATTRIBUTE_UNUSED, segT sec) link_once_flags = (flags & SEC_LINK_ONCE); /* Flags might not be set yet. */ - if (!link_once_flags) - { - static size_t len = sizeof ".gnu.linkonce.t."; + if (!link_once_flags + && strncmp (segment_name (sec), ".gnu.linkonce.", linkonce_len) == 0) + link_once_flags = SEC_LINK_ONCE; - if (strncmp (segment_name (sec), ".gnu.linkonce.t.", len - 1) == 0) - link_once_flags = SEC_LINK_ONCE; - } return (link_once_flags != 0); } @@ -4946,12 +4897,8 @@ md_begin (void) linkrelax = 1; - /* Set up the .literal, .fini.literal and .init.literal sections. */ + /* Set up the literal sections. */ memset (&default_lit_sections, 0, sizeof (default_lit_sections)); - default_lit_sections.init_lit_seg_name = INIT_LITERAL_SECTION_NAME; - default_lit_sections.fini_lit_seg_name = FINI_LITERAL_SECTION_NAME; - default_lit_sections.lit_seg_name = LITERAL_SECTION_NAME; - default_lit_sections.lit4_seg_name = LIT4_SECTION_NAME; subseg_set (current_section, current_subsec); @@ -9694,15 +9641,17 @@ xtensa_move_literals (void) sym_list *lit; mark_literal_frags (literal_head->next); - mark_literal_frags (init_literal_head->next); - mark_literal_frags (fini_literal_head->next); if (use_literal_section) return; - segment = literal_head->next; - while (segment) + for (segment = literal_head->next; segment; segment = segment->next) { + /* Keep the literals for .init and .fini in separate sections. */ + if (!strcmp (segment_name (segment->seg), INIT_SECTION_NAME) + || !strcmp (segment_name (segment->seg), FINI_SECTION_NAME)) + continue; + frchain_from = seg_info (segment->seg)->frchainP; search_frag = frchain_from->frch_root; literal_pool = NULL; @@ -9786,7 +9735,6 @@ xtensa_move_literals (void) } frchain_from->fix_tail = NULL; xtensa_restore_emit_state (&state); - segment = segment->next; } /* Now fix up the SEGMENT value for all the literal symbols. */ @@ -9867,8 +9815,6 @@ xtensa_reorder_segments (void) /* Now that we have the last section, push all the literal sections to the end. */ xtensa_reorder_seg_list (literal_head, last_sec); - xtensa_reorder_seg_list (init_literal_head, last_sec); - xtensa_reorder_seg_list (fini_literal_head, last_sec); /* Now perform the final error check. */ for (sec = stdoutput->sections; sec != NULL; sec = sec->next) @@ -9886,10 +9832,8 @@ xtensa_switch_to_literal_fragment (emit_state *result) { if (directive_state[directive_absolute_literals]) { - cache_literal_section (0, default_lit_sections.lit4_seg_name, - &default_lit_sections.lit4_seg, FALSE); - xtensa_switch_section_emit_state (result, - default_lit_sections.lit4_seg, 0); + segT lit4_seg = cache_literal_section (TRUE); + xtensa_switch_section_emit_state (result, lit4_seg, 0); } else xtensa_switch_to_non_abs_literal_fragment (result); @@ -9903,17 +9847,11 @@ xtensa_switch_to_literal_fragment (emit_state *result) static void xtensa_switch_to_non_abs_literal_fragment (emit_state *result) { - /* When we mark a literal pool location, we want to put a frag in - the literal pool that points to it. But to do that, we want to - switch_to_literal_fragment. But literal sections don't have - literal pools, so their location is always null, so we would - recurse forever. This is kind of hacky, but it works. */ - static bfd_boolean recursive = FALSE; fragS *pool_location = get_literal_pool_location (now_seg); + segT lit_seg; bfd_boolean is_init = (now_seg && !strcmp (segment_name (now_seg), INIT_SECTION_NAME)); - bfd_boolean is_fini = (now_seg && !strcmp (segment_name (now_seg), FINI_SECTION_NAME)); @@ -9923,39 +9861,20 @@ xtensa_switch_to_non_abs_literal_fragment (emit_state *result) && !is_init && ! is_fini) { as_bad (_("literal pool location required for text-section-literals; specify with .literal_position")); + + /* When we mark a literal pool location, we want to put a frag in + the literal pool that points to it. But to do that, we want to + switch_to_literal_fragment. But literal sections don't have + literal pools, so their location is always null, so we would + recurse forever. This is kind of hacky, but it works. */ + recursive = TRUE; xtensa_mark_literal_pool_location (); recursive = FALSE; } - /* Special case: If we are in the ".fini" or ".init" section, then - we will ALWAYS be generating to the ".fini.literal" and - ".init.literal" sections. */ - - if (is_init) - { - cache_literal_section (init_literal_head, - default_lit_sections.init_lit_seg_name, - &default_lit_sections.init_lit_seg, TRUE); - xtensa_switch_section_emit_state (result, - default_lit_sections.init_lit_seg, 0); - } - else if (is_fini) - { - cache_literal_section (fini_literal_head, - default_lit_sections.fini_lit_seg_name, - &default_lit_sections.fini_lit_seg, TRUE); - xtensa_switch_section_emit_state (result, - default_lit_sections.fini_lit_seg, 0); - } - else - { - cache_literal_section (literal_head, - default_lit_sections.lit_seg_name, - &default_lit_sections.lit_seg, TRUE); - xtensa_switch_section_emit_state (result, - default_lit_sections.lit_seg, 0); - } + lit_seg = cache_literal_section (FALSE); + xtensa_switch_section_emit_state (result, lit_seg, 0); if (!use_literal_section && !is_init && !is_fini @@ -9999,49 +9918,129 @@ xtensa_restore_emit_state (emit_state *state) } -/* Get a segment of a given name. If the segment is already - present, return it; otherwise, create a new one. */ +/* Predicate function used to look up a section in a particular group. */ -static void -cache_literal_section (seg_list *head, - const char *name, - segT *pseg, - bfd_boolean is_code) +static bfd_boolean +match_section_group (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf) { - segT current_section = now_seg; - int current_subsec = now_subseg; - segT seg; + const char *gname = inf; + const char *group_name = elf_group_name (sec); + + return (group_name == gname + || (group_name != NULL + && gname != NULL + && strcmp (group_name, gname) == 0)); +} - if (*pseg != 0) - return; - /* Check if the named section exists. */ - for (seg = stdoutput->sections; seg; seg = seg->next) +/* Get the literal section to be used for the current text section. + The result may be cached in the default_lit_sections structure. */ + +static segT +cache_literal_section (bfd_boolean use_abs_literals) +{ + const char *text_name, *group_name = 0; + char *base_name, *name, *suffix; + segT *pcached; + segT seg, current_section; + int current_subsec; + bfd_boolean linkonce = FALSE; + + /* Save the current section/subsection. */ + current_section = now_seg; + current_subsec = now_subseg; + + /* Clear the cached values if they are no longer valid. */ + if (now_seg != default_lit_sections.current_text_seg) { - if (!strcmp (segment_name (seg), name)) - break; + default_lit_sections.current_text_seg = now_seg; + default_lit_sections.lit_seg = NULL; + default_lit_sections.lit4_seg = NULL; + } + + /* Check if the literal section is already cached. */ + if (use_abs_literals) + pcached = &default_lit_sections.lit4_seg; + else + pcached = &default_lit_sections.lit_seg; + + if (*pcached) + return *pcached; + + text_name = default_lit_sections.lit_prefix; + if (! text_name || ! *text_name) + { + text_name = segment_name (current_section); + group_name = elf_group_name (current_section); + linkonce = (current_section->flags & SEC_LINK_ONCE) != 0; + } + + base_name = use_abs_literals ? ".lit4" : ".literal"; + if (group_name) + { + name = xmalloc (strlen (base_name) + strlen (group_name) + 2); + sprintf (name, "%s.%s", base_name, group_name); + } + else if (strncmp (text_name, ".gnu.linkonce.", linkonce_len) == 0) + { + suffix = strchr (text_name + linkonce_len, '.'); + + name = xmalloc (linkonce_len + strlen (base_name) + 1 + + (suffix ? strlen (suffix) : 0)); + strcpy (name, ".gnu.linkonce"); + strcat (name, base_name); + if (suffix) + strcat (name, suffix); + linkonce = TRUE; + } + else + { + /* If the section name ends with ".text", then replace that suffix + instead of appending an additional suffix. */ + size_t len = strlen (text_name); + if (len >= 5 && strcmp (text_name + len - 5, ".text") == 0) + len -= 5; + + name = xmalloc (len + strlen (base_name) + 1); + strcpy (name, text_name); + strcpy (name + len, base_name); } - if (!seg) + /* Canonicalize section names to allow renaming literal sections. + The group name, if any, came from the current text section and + has already been canonicalized. */ + name = tc_canonicalize_symbol_name (name); + + seg = bfd_get_section_by_name_if (stdoutput, name, match_section_group, + (void *) group_name); + if (! seg) { - /* Create a new literal section. */ - seg = subseg_new (name, (subsegT) 0); - if (head) + flagword flags; + + seg = subseg_force_new (name, 0); + + if (! use_abs_literals) { - /* Add the newly created literal segment to the specified list. */ + /* Add the newly created literal segment to the list. */ seg_list *n = (seg_list *) xmalloc (sizeof (seg_list)); n->seg = seg; - n->next = head->next; - head->next = n; + n->next = literal_head->next; + literal_head->next = n; } - bfd_set_section_flags (stdoutput, seg, SEC_HAS_CONTENTS | - SEC_READONLY | SEC_ALLOC | SEC_LOAD - | (is_code ? SEC_CODE : SEC_DATA)); + + flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD + | (linkonce ? (SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD) : 0) + | (use_abs_literals ? SEC_DATA : SEC_CODE)); + + elf_group_name (seg) = group_name; + + bfd_set_section_flags (stdoutput, seg, flags); bfd_set_section_alignment (stdoutput, seg, 2); } - *pseg = seg; + *pcached = seg; subseg_set (current_section, current_subsec); + return seg; } @@ -10060,7 +10059,6 @@ static void xtensa_create_property_segments static void xtensa_create_xproperty_segments (frag_flags_fn, const char *, xt_section_type); static segment_info_type *retrieve_segment_info (segT); -static segT retrieve_xtensa_section (char *); static bfd_boolean section_has_property (segT, frag_predicate); static bfd_boolean section_has_xproperty (segT, frag_flags_fn); static void add_xt_block_frags @@ -10078,8 +10076,6 @@ void xtensa_post_relax_hook (void) { xtensa_move_seg_list_to_beginning (literal_head); - xtensa_move_seg_list_to_beginning (init_literal_head); - xtensa_move_seg_list_to_beginning (fini_literal_head); xtensa_find_unmarked_state_frags (); @@ -10135,9 +10131,8 @@ xtensa_create_property_segments (frag_predicate property_function, if (section_has_property (sec, property_function)) { - char *property_section_name = - xtensa_get_property_section_name (sec, section_name_base); - segT insn_sec = retrieve_xtensa_section (property_section_name); + segT insn_sec = + xtensa_get_property_section (sec, section_name_base); segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec); xtensa_block_info **xt_blocks = &xt_seg_info->tc_segment_info_data.blocks[sec_type]; @@ -10268,9 +10263,8 @@ xtensa_create_xproperty_segments (frag_flags_fn flag_fn, if (section_has_xproperty (sec, flag_fn)) { - char *property_section_name = - xtensa_get_property_section_name (sec, section_name_base); - segT insn_sec = retrieve_xtensa_section (property_section_name); + segT insn_sec = + xtensa_get_property_section (sec, section_name_base); segment_info_type *xt_seg_info = retrieve_segment_info (insn_sec); xtensa_block_info **xt_blocks = &xt_seg_info->tc_segment_info_data.blocks[sec_type]; @@ -10414,29 +10408,6 @@ retrieve_segment_info (segT seg) } -static segT -retrieve_xtensa_section (char *sec_name) -{ - bfd *abfd = stdoutput; - flagword flags, out_flags, link_once_flags; - segT s; - - flags = bfd_get_section_flags (abfd, now_seg); - link_once_flags = (flags & SEC_LINK_ONCE); - if (link_once_flags) - link_once_flags |= (flags & SEC_LINK_DUPLICATES); - out_flags = (SEC_RELOC | SEC_HAS_CONTENTS | SEC_READONLY | link_once_flags); - - s = bfd_make_section_old_way (abfd, sec_name); - if (s == NULL) - as_bad (_("could not create section %s"), sec_name); - if (!bfd_set_section_flags (abfd, s, out_flags)) - as_bad (_("invalid flag combination on section %s"), sec_name); - - return s; -} - - static bfd_boolean section_has_property (segT sec, frag_predicate property_function) { diff --git a/gas/doc/c-xtensa.texi b/gas/doc/c-xtensa.texi index 2a1fb54b0b0..1a683fc1ffa 100644 --- a/gas/doc/c-xtensa.texi +++ b/gas/doc/c-xtensa.texi @@ -37,8 +37,8 @@ special options: @kindex --text-section-literals @kindex --no-text-section-literals Control the treatment of literal pools. The default is -@samp{--no-@-text-@-section-@-literals}, which places literals in a -separate section in the output file. This allows the literal pool to be +@samp{--no-@-text-@-section-@-literals}, which places literals in +separate sections in the output file. This allows the literal pool to be placed in a data RAM/ROM. With @samp{--text-@-section-@-literals}, the literals are interspersed in the text section in order to keep them as close as possible to their references. This may be necessary for large @@ -46,6 +46,7 @@ assembly files, where the literals would otherwise be out of range of the @code{L32R} instructions in the text section. These options only affect literals referenced via PC-relative @code{L32R} instructions; literals for absolute mode @code{L32R} instructions are handled separately. +@xref{Literal Directive, ,literal}. @item --absolute-literals | --no-absolute-literals @kindex --absolute-literals @@ -617,13 +618,14 @@ can be used to load a pointer to the symbol @code{sym} into register @code{ENTRY} and @code{L32R} instructions; instead, the assembler puts the data in a literal pool. -Literal pools for absolute mode @code{L32R} instructions -(@pxref{Absolute Literals Directive}) are placed in a separate -@code{.lit4} section. By default literal pools for PC-relative mode -@code{L32R} instructions are placed in a separate @code{.literal} -section; however, when using the @samp{--text-@-section-@-literals} +Literal pools are placed by default in separate literal sections; +however, when using the @samp{--text-@-section-@-literals} option (@pxref{Xtensa Options, ,Command Line Options}), the literal -pools are placed in the current section. These text section literal +pools for PC-relative mode @code{L32R} instructions +are placed in the current section.@footnote{Literals for the +@code{.init} and @code{.fini} sections are always placed in separate +sections, even when @samp{--text-@-section-@-literals} is enabled.} +These text section literal pools are created automatically before @code{ENTRY} instructions and manually after @samp{.literal_position} directives (@pxref{Literal Position Directive, ,literal_position}). If there are no preceding @@ -631,6 +633,46 @@ Position Directive, ,literal_position}). If there are no preceding must be used to place the text section literal pools; otherwise, @command{@value{AS}} will report an error. +When literals are placed in separate sections, the literal section names +are derived from the names of the sections where the literals are +defined. The base literal section names are @code{.literal} for +PC-relative mode @code{L32R} instructions and @code{.lit4} for absolute +mode @code{L32R} instructions (@pxref{Absolute Literals Directive, +,absolute-literals}). These base names are used for literals defined in +the default @code{.text} section. For literals defined in other +sections or within the scope of a @code{literal_prefix} directive +(@pxref{Literal Prefix Directive, ,literal_prefix}), the following rules +determine the literal section name: + +@enumerate +@item +If the current section is a member of a section group, the literal +section name includes the group name as a suffix to the base +@code{.literal} or @code{.lit4} name, with a period to separate the base +name and group name. The literal section is also made a member of the +group. + +@item +If the current section name (or @code{literal_prefix} value) begins with +``@code{.gnu.linkonce.@var{kind}.}'', the literal section name is formed +by replacing ``@code{.@var{kind}}'' with the base @code{.literal} or +@code{.lit4} name. For example, for literals defined in a section named +@code{.gnu.linkonce.t.func}, the literal section will be +@code{.gnu.linkonce.literal.func} or @code{.gnu.linkonce.lit4.func}. + +@item +If the current section name (or @code{literal_prefix} value) ends with +@code{.text}, the literal section name is formed by replacing that +suffix with the base @code{.literal} or @code{.lit4} name. For example, +for literals defined in a section named @code{.iram0.text}, the literal +section will be @code{.iram0.literal} or @code{.iram0.lit4}. + +@item +If none of the preceding conditions apply, the literal section name is +formed by adding the base @code{.literal} or @code{.lit4} name as a +suffix to the current section name (or @code{literal_prefix} value). +@end enumerate + @node Literal Position Directive @subsection literal_position @cindex @code{literal_position} directive @@ -679,45 +721,24 @@ continue: @subsection literal_prefix @cindex @code{literal_prefix} directive -The @code{literal_prefix} directive allows you to specify different -sections to hold literals from different portions of an assembly file. -With this directive, a single assembly file can be used to generate code -into multiple sections, including literals generated by the assembler. +The @code{literal_prefix} directive allows you to override the default +literal section names, which are derived from the names of the sections +where the literals are defined. @smallexample .begin literal_prefix [@var{name}] .end literal_prefix @end smallexample -By default the assembler places literal pools in sections separate from -the instructions, using the default literal section names of -@code{.literal} for PC-relative mode @code{L32R} instructions and -@code{.lit4} for absolute mode @code{L32R} instructions (@pxref{Absolute -Literals Directive}). The @code{literal_prefix} directive causes -different literal sections to be used for the code inside the delimited -region. The new literal sections are determined by including @var{name} -as a prefix to the default literal section names. If the @var{name} +For literals defined within the delimited region, the literal section +names are derived from the @var{name} argument instead of the name of +the current section. The rules used to derive the literal section names +do not change. @xref{Literal Directive, ,literal}. If the @var{name} argument is omitted, the literal sections revert to the defaults. This directive has no effect when using the @samp{--text-@-section-@-literals} option (@pxref{Xtensa Options, ,Command Line Options}). -Except for two special cases, the assembler determines the new literal -sections by simply prepending @var{name} to the default section names, -resulting in @code{@var{name}.literal} and @code{@var{name}.lit4} -sections. The @code{literal_prefix} directive is often used with the -name of the current text section as the prefix argument. To facilitate -this usage, the assembler uses special case rules when it recognizes -@var{name} as a text section name. First, if @var{name} ends with -@code{.text}, that suffix is not included in the literal section name. -For example, if @var{name} is @code{.iram0.text}, then the literal -sections will be @code{.iram0.literal} and @code{.iram0.lit4}. Second, -if @var{name} begins with @code{.gnu.linkonce.t.}, then the literal -section names are formed by replacing the @code{.t} substring with -@code{.literal} and @code{.lit4}. For example, if @var{name} is -@code{.gnu.linkonce.t.func}, the literal sections will be -@code{.gnu.linkonce.literal.func} and @code{.gnu.linkonce.lit4.func}. - @node Absolute Literals Directive @subsection absolute-literals @cindex @code{absolute-literals} directive diff --git a/ld/ChangeLog b/ld/ChangeLog index 8b73d137830..6c972542315 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2006-08-24 Bob Wilson + + * emulparams/elf32xtensa.sh (.xt.prop): Add .xt.prop.*. + * scripttempl/elfxtensa.sc (.text): Add .literal.*. + 2006-08-24 Pedro Alves * ldlang.c (lang_size_sections_1, lang_assignment_statement_enum): diff --git a/ld/emulparams/elf32xtensa.sh b/ld/emulparams/elf32xtensa.sh index c4b13b9a511..1abef5d86b8 100644 --- a/ld/emulparams/elf32xtensa.sh +++ b/ld/emulparams/elf32xtensa.sh @@ -31,5 +31,5 @@ OTHER_READWRITE_SECTIONS=" OTHER_SECTIONS=" .xt.lit 0 : { *(.xt.lit${RELOCATING+ .xt.lit.* .gnu.linkonce.p.*}) } .xt.insn 0 : { *(.xt.insn${RELOCATING+ .gnu.linkonce.x.*}) } - .xt.prop 0 : { *(.xt.prop${RELOCATING+ .gnu.linkonce.prop.*}) } + .xt.prop 0 : { *(.xt.prop${RELOCATING+ .xt.prop.* .gnu.linkonce.prop.*}) } " diff --git a/ld/scripttempl/elfxtensa.sc b/ld/scripttempl/elfxtensa.sc index 9c3aa1fe5e7..63c8e8c6c9a 100644 --- a/ld/scripttempl/elfxtensa.sc +++ b/ld/scripttempl/elfxtensa.sc @@ -309,7 +309,7 @@ cat <