mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
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.*.
This commit is contained in:
parent
ca0ef6cdf0
commit
74869ac7a4
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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.*}) }
|
||||
"
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user