This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Don't set DT_TEXTREL flag for Xtensa
- From: Bob Wilson <bwilson at tensilica dot com>
- To: binutils at sources dot redhat dot com
- Date: Mon, 22 Mar 2004 17:42:53 -0800
- Subject: Don't set DT_TEXTREL flag for Xtensa
- Organization: Tensilica, Inc.
Use of the DT_TEXTREL dynamic entry for Xtensa shared objects is not compatible
with the way the Xtensa runtime loader handles literal pools. The literal pools
are located within the text section, and the loader reads a special "literal
table" to locate the literal pools and make them writable. If the DT_TEXTREL
flag is set, the entire text section reverts to being read-only after the
initial relocations have been performed, thereby undoing the protection changes
for pages containing literal pools. This problem went undetected for quite a
while because it was masked by a bug in the Xtensa port of the 2.4 Linux kernel.
This patch changes the assembler to always emit literal table entries, even when
using the --text-section-literals assembler option. The previous plan was to
handle --text-section-literals by setting DT_TEXTREL. With this patch, code
assembled with --text-section-literals will at least work, even if the literal
tables are larger than one would like. I'm not very concerned about this
because it doesn't really make much sense to use --text-section-literals on a
system with shared objects, anyway. I'm thinking of some ways to clean this up
in the longer term.
The patch also changes the linker to make it stop setting DT_TEXTREL when it
encounters a relocation on a read-only section and outside a literal pool.
Instead, it now checks the literal tables when emitting dynamic relocations, and
if there is a dynamic relocation outside a literal pool, it is treated as an
error.
I tested this by running the testsuite with an xtensa-elf target (no shared
libraries), and by building glibc and booting a board with it. Committed on the
mainline and 2.15 branch.
bfd/ChangeLog:
* elf32-xtensa.c (elf_xtensa_check_relocs): Remove code to read
literal tables and check for relocs outside of literal pools.
(elf_xtensa_make_sym_local): Don't clear ELF_LINK_NON_GOT_REF flag.
(elf_xtensa_fix_refcounts): Don't check ELF_LINK_NON_GOT_REF or
set DF_TEXTREL.
(elf_xtensa_size_dynamic_sections): Don't add DT_TEXTREL entry.
(elf_xtensa_relocate_section): Read literal tables and check for
dynamic relocations in read-only sections and not in literal pools.
gas/ChangeLog:
* config/tc-xtensa.c (xtensa_post_relax_hook): Create literal
tables even when use_literal_section flag is not set.
Index: elf32-xtensa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-xtensa.c,v
retrieving revision 1.21
diff -u -p -r1.21 elf32-xtensa.c
--- elf32-xtensa.c 22 Mar 2004 02:28:17 -0000 1.21
+++ elf32-xtensa.c 23 Mar 2004 01:12:12 -0000
@@ -619,8 +619,6 @@ elf_xtensa_check_relocs (abfd, info, sec
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
const Elf_Internal_Rela *rel_end;
- property_table_entry *lit_table;
- int ltblsize;
if (info->relocatable)
return TRUE;
@@ -628,11 +626,6 @@ elf_xtensa_check_relocs (abfd, info, sec
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
- ltblsize = xtensa_read_table_entries (abfd, sec, &lit_table,
- XTENSA_LIT_SEC_NAME);
- if (ltblsize < 0)
- return FALSE;
-
rel_end = relocs + sec->reloc_count;
for (rel = relocs; rel < rel_end; rel++)
{
@@ -669,11 +662,6 @@ elf_xtensa_check_relocs (abfd, info, sec
if ((sec->flags & SEC_ALLOC) != 0)
{
- if ((sec->flags & SEC_READONLY) != 0
- && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
- sec->vma + rel->r_offset))
- h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
if (h->got.refcount <= 0)
h->got.refcount = 1;
else
@@ -689,11 +677,6 @@ elf_xtensa_check_relocs (abfd, info, sec
if ((sec->flags & SEC_ALLOC) != 0)
{
- if ((sec->flags & SEC_READONLY) != 0
- && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
- sec->vma + rel->r_offset))
- h->elf_link_hash_flags |= ELF_LINK_NON_GOT_REF;
-
if (h->plt.refcount <= 0)
{
h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
@@ -736,14 +719,6 @@ elf_xtensa_check_relocs (abfd, info, sec
elf_local_got_refcounts (abfd) = local_got_refcounts;
}
local_got_refcounts[r_symndx] += 1;
-
- /* If the relocation is not inside the GOT, the DF_TEXTREL
- flag needs to be set. */
- if (info->shared
- && (sec->flags & SEC_READONLY) != 0
- && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
- sec->vma + rel->r_offset))
- info->flags |= DF_TEXTREL;
}
break;
@@ -774,7 +749,6 @@ elf_xtensa_check_relocs (abfd, info, sec
}
}
- free (lit_table);
return TRUE;
}
@@ -1044,7 +1018,6 @@ elf_xtensa_make_sym_local (info, h)
else
{
/* Don't need any dynamic relocations at all. */
- h->elf_link_hash_flags &= ~ELF_LINK_NON_GOT_REF;
h->plt.refcount = 0;
h->got.refcount = 0;
}
@@ -1064,11 +1037,6 @@ elf_xtensa_fix_refcounts (h, arg)
if (! xtensa_elf_dynamic_symbol_p (h, info))
elf_xtensa_make_sym_local (info, h);
- /* If the symbol has a relocation outside the GOT, set the
- DF_TEXTREL flag. */
- if ((h->elf_link_hash_flags & ELF_LINK_NON_GOT_REF) != 0)
- info->flags |= DF_TEXTREL;
-
return TRUE;
}
@@ -1391,12 +1359,6 @@ elf_xtensa_size_dynamic_sections (output
return FALSE;
}
- if ((info->flags & DF_TEXTREL) != 0)
- {
- if (!add_dynamic_entry (DT_TEXTREL, 0))
- return FALSE;
- }
-
if (!add_dynamic_entry (DT_XTENSA_GOT_LOC_OFF, 0)
|| !add_dynamic_entry (DT_XTENSA_GOT_LOC_SZ, 0))
return FALSE;
@@ -1851,6 +1813,8 @@ elf_xtensa_relocate_section (output_bfd,
struct elf_link_hash_entry **sym_hashes;
asection *srelgot, *srelplt;
bfd *dynobj;
+ property_table_entry *lit_table = 0;
+ int ltblsize = 0;
char *error_message = NULL;
if (xtensa_default_isa == NULL)
@@ -1868,6 +1832,14 @@ elf_xtensa_relocate_section (output_bfd,
srelplt = bfd_get_section_by_name (dynobj, ".rela.plt");
}
+ if (elf_hash_table (info)->dynamic_sections_created)
+ {
+ ltblsize = xtensa_read_table_entries (input_bfd, input_section,
+ &lit_table, XTENSA_LIT_SEC_NAME);
+ if (ltblsize < 0)
+ return FALSE;
+ }
+
rel = relocs;
relend = relocs + input_section->reloc_count;
for (; rel < relend; rel++)
@@ -2068,6 +2040,21 @@ elf_xtensa_relocate_section (output_bfd,
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
+ /* Complain if the relocation is in a read-only section
+ and not in a literal pool. */
+ if ((input_section->flags & SEC_READONLY) != 0
+ && !elf_xtensa_in_literal_pool (lit_table, ltblsize,
+ input_section->vma
+ + rel->r_offset))
+ {
+ error_message =
+ _("dynamic relocation in read-only section");
+ if (!((*info->callbacks->reloc_dangerous)
+ (info, error_message, input_bfd, input_section,
+ rel->r_offset)))
+ return FALSE;
+ }
+
if (dynamic_symbol)
{
outrel.r_addend = rel->r_addend;
@@ -2154,6 +2141,9 @@ elf_xtensa_relocate_section (output_bfd,
return FALSE;
}
}
+
+ if (lit_table)
+ free (lit_table);
return TRUE;
}
Index: config/tc-xtensa.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-xtensa.c,v
retrieving revision 1.8
diff -u -p -r1.8 tc-xtensa.c
--- config/tc-xtensa.c 19 Mar 2004 22:35:32 -0000 1.8
+++ config/tc-xtensa.c 22 Mar 2004 20:01:46 -0000
@@ -7888,10 +7888,9 @@ xtensa_post_relax_hook ()
xtensa_create_property_segments (get_frag_is_insn,
XTENSA_INSN_SEC_NAME,
xt_insn_sec);
- if (use_literal_section)
- xtensa_create_property_segments (get_frag_is_literal,
- XTENSA_LIT_SEC_NAME,
- xt_literal_sec);
+ xtensa_create_property_segments (get_frag_is_literal,
+ XTENSA_LIT_SEC_NAME,
+ xt_literal_sec);
}