* 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.*.
This commit is contained in:
Bob Wilson 2006-08-25 00:08:55 +00:00
parent ca0ef6cdf0
commit 74869ac7a4
8 changed files with 342 additions and 249 deletions

View file

@ -1,3 +1,12 @@
2006-08-24 Bob Wilson <bob.wilson@acm.org>
* 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 <Frediano.Ziglio@vodafone.com>
* archive.c (hpux_uid_gid_encode): Fix thinko decrementing "cnt"

View file

@ -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)
{
if (strncmp (sec->name, ".gnu.linkonce.", linkonce_len) == 0)
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)
{
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);
return prop_sec_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;
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

View file

@ -1,3 +1,42 @@
2006-08-24 Bob Wilson <bob.wilson@acm.org>
* 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 <joseph@codesourcery.com>
* config/tc-arm.c (s_arm_unwind_save_mmxwr): Correct condition for

View file

@ -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). */
/* Skip the name in the input line. */
input_line_pointer += len;
newname = xmalloc (len + strlen (".literal") + 1);
newname4 = xmalloc (len + strlen (".lit4") + 1);
default_lit_sections.lit_prefix = name;
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;
strcpy (newname, name);
strcpy (newname4, 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;
}
if (!seg)
/* 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)
{
/* Create a new literal section. */
seg = subseg_new (name, (subsegT) 0);
if (head)
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);
}
/* 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)
{
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)
{

View file

@ -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

View file

@ -1,3 +1,8 @@
2006-08-24 Bob Wilson <bob.wilson@acm.org>
* emulparams/elf32xtensa.sh (.xt.prop): Add .xt.prop.*.
* scripttempl/elfxtensa.sc (.text): Add .literal.*.
2006-08-24 Pedro Alves <pedro_alves@portugalmail.pt>
* ldlang.c (lang_size_sections_1, lang_assignment_statement_enum):

View file

@ -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.*}) }
"

View file

@ -309,7 +309,7 @@ cat <<EOF
${RELOCATING+${INIT_END}}
${RELOCATING+${TEXT_START_SYMBOLS}}
*(.literal .text .stub${RELOCATING+ .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*})
*(.literal .text .stub${RELOCATING+ .literal.* .text.* .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*})
KEEP (*(.text.*personality*))
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)