Discussion:
dynrelro section for read-only dynamic symbols copied into executable
(too old to reply)
Alan Modra
2016-12-26 05:44:48 UTC
Permalink
Variables defined in shared libraries are copied into an executable's
.bss section when code in the executable is non-PIC and thus would
require dynamic text relocations to access the variable directly in
the shared library. Recent x86 toolchains also copy variables into
the executable to gain a small speed improvement.

The problem is that if the variable was originally read-only, the copy
in .bss is writable, potentially opening a security hole. This patch
cures that problem by putting the copy in a section that becomes
read-only after ld.so relocation, provided -z relro is in force.

These targets should now be OK: aarch64, arm, hppa, i386, metag,
microblaze, mips, mips64, nios2, or1k, ppc, ppc64, s390, s390x, sparc,
sparc64, tic6x, tilegx, tilepro and x86-64. However, not much testing
has been done yet.. I applied fixes for riscv too, before realizing
that riscv scripts are broken for relro.

The patch also fixes a microblaze linker segfault on attempting to
use dynamic bss variables.

Of the targets I regularly test, the following fail the new test:
am33_2.0-linux +FAIL: pr20995
arc-linux-uclibc +FAIL: pr20995
crisv32-linux +FAIL: pr20995
hppa64-hp-hpux11.23 +FAIL: pr20995
hppa64-linux +FAIL: pr20995
i370-linux +FAIL: Build pr20995.so
i370-linux +FAIL: pr20995
m68k-elf +FAIL: pr20995
m68k-linux +FAIL: pr20995
mips64-linux +FAIL: pr20995
mipsel-linux-gnu +FAIL: pr20995
mipsisa32el-linux +FAIL: pr20995
mips-linux +FAIL: pr20995
mn10300-elf +FAIL: pr20995
riscv32-elf +FAIL: pr20995
riscv64-elf +FAIL: pr20995
score-elf +FAIL: pr20995
sh-linux +FAIL: pr20995
shl-unknown-netbsdelf +FAIL: pr20995
tic6x-elf +FAIL: pr20995
vax-netbsdelf +FAIL: pr20995

mips apparently needs a tweak to run the testcase with the right
flags. riscv scripts are hosed for -z relro. tic6x doesn't want to
create any dynamic relocs for the testcase. The rest are targets that
I haven't converted over to use the new dynamic sections for read-only
variables. I don't intend to do much more on this over Christmas
and New Year, so if your favourite target is one of those that fails
the test it's likely that 2.28 will go out without the fix unless
target maintainers step up.

bfd/
PR ld/20995
* elf-bfd.h (struct elf_link_hash_table): Add sdynrelro and
sreldynrelro.
(struct elf_backend_data): Add want_dynrelro.
* elfxx-target.h (elf_backend_want_dynrelro): Define.
(elfNN_bed): Update initializer.
* elflink.c (_bfd_elf_create_dynamic_sections): Create
sdynrelro and sreldynrelro sections.
* elf32-arm.c (elf32_arm_adjust_dynamic_symbol): Place variables
copied into the executable from read-only sections into sdynrelro.
(elf32_arm_size_dynamic_sections): Handle sdynrelro.
(elf32_arm_finish_dynamic_symbol): Select sreldynrelro for
dynamic relocs in sdynrelro.
(elf_backend_want_dynrelro): Define.
* elf32-hppa.c (elf32_hppa_adjust_dynamic_symbol)
(elf32_hppa_size_dynamic_sections, elf32_hppa_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-i386.c (elf_i386_adjust_dynamic_symbol)
(elf_i386_size_dynamic_sections, elf_i386_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-metag.c (elf_metag_adjust_dynamic_symbol)
(elf_metag_size_dynamic_sections, elf_metag_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-microblaze.c (microblaze_elf_adjust_dynamic_symbol)
(microblaze_elf_size_dynamic_sections)
(microblaze_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-nios2.c (nios2_elf32_finish_dynamic_symbol)
(nios2_elf32_adjust_dynamic_symbol)
(nios2_elf32_size_dynamic_sections)
(elf_backend_want_dynrelro): As above.
* elf32-or1k.c (or1k_elf_finish_dynamic_symbol)
(or1k_elf_adjust_dynamic_symbol, or1k_elf_size_dynamic_sections)
(elf_backend_want_dynrelro): As above.
* elf32-ppc.c (ppc_elf_adjust_dynamic_symbol)
(ppc_elf_size_dynamic_sections, ppc_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-s390.c (elf_s390_adjust_dynamic_symbol)
(elf_s390_size_dynamic_sections, elf_s390_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-tic6x.c (elf32_tic6x_adjust_dynamic_symbol)
(elf32_tic6x_size_dynamic_sections)
(elf32_tic6x_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-tilepro.c (tilepro_elf_adjust_dynamic_symbol)
(tilepro_elf_size_dynamic_sections)
(tilepro_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol)
(ppc64_elf_size_dynamic_sections, ppc64_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf64-s390.c (elf_s390_adjust_dynamic_symbol)
(elf_s390_size_dynamic_sections, elf_s390_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol)
(elf_x86_64_size_dynamic_sections)
(elf_x86_64_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elfnn-aarch64.c (elfNN_aarch64_adjust_dynamic_symbol)
(elfNN_aarch64_size_dynamic_sections)
(elfNN_aarch64_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elfnn-riscv.c (riscv_elf_adjust_dynamic_symbol)
(riscv_elf_size_dynamic_sections, riscv_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elfxx-mips.c (_bfd_mips_elf_adjust_dynamic_symbol)
(_bfd_mips_elf_size_dynamic_sections)
(_bfd_mips_vxworks_finish_dynamic_symbol): As above.
* elfxx-sparc.c (_bfd_sparc_elf_adjust_dynamic_symbol)
(_bfd_sparc_elf_size_dynamic_sections)
(_bfd_sparc_elf_finish_dynamic_symbol): As above.
* elfxx-tilegx.c (tilegx_elf_adjust_dynamic_symbol)
(tilegx_elf_size_dynamic_sections)
(tilegx_elf_finish_dynamic_symbol): As above.
* elf32-mips.c (elf_backend_want_dynrelro): Define.
* elf64-mips.c (elf_backend_want_dynrelro): Define.
* elf32-sparc.c (elf_backend_want_dynrelro): Define.
* elf64-sparc.c (elf_backend_want_dynrelro): Define.
* elf32-tilegx.c (elf_backend_want_dynrelro): Define.
* elf64-tilegx.c (elf_backend_want_dynrelro): Define.
* elf32-microblaze.c (microblaze_elf_adjust_dynamic_symbol): Tidy.
(microblaze_elf_size_dynamic_sections): Handle sdynbss.
* elf32-nios2.c (nios2_elf32_size_dynamic_sections): Make use
of linker shortcuts to dynamic sections rather than comparing
names. Correctly set "got" flag.
ld/
PR ld/20995
* testsuite/ld-arm/farcall-mixed-app-v5.d: Update to suit changed
stub hash table traversal caused by section id increment. Accept
the previous output too.
* testsuite/ld-arm/farcall-mixed-app.d: Likewise.
* testsuite/ld-arm/farcall-mixed-lib-v4t.d: Likewise.
* testsuite/ld-arm/farcall-mixed-lib.d: Likewise.
* testsuite/ld-elf/pr20995a.s, * testsuite/ld-elf/pr20995b.s,
* testsuite/ld-elf/pr20995.r: New test.
* testsuite/ld-elf/elf.exp: Run it.

diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 4093434..1c634d8 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -597,6 +597,8 @@ struct elf_link_hash_table
asection *srelplt;
asection *sdynbss;
asection *srelbss;
+ asection *sdynrelro;
+ asection *sreldynrelro;
asection *igotplt;
asection *iplt;
asection *irelplt;
@@ -1451,6 +1453,7 @@ struct elf_backend_data
unsigned can_refcount : 1;
unsigned want_got_sym : 1;
unsigned want_dynbss : 1;
+ unsigned want_dynrelro : 1;

/* Targets which do not support physical addressing often require
that the p_paddr field in the section header to be set to zero.
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 4761136..384063e 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -15264,7 +15264,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
struct elf_link_hash_entry * h)
{
bfd * dynobj;
- asection * s;
+ asection *s, *srel;
struct elf32_arm_link_hash_entry * eh;
struct elf32_arm_link_hash_table *globals;

@@ -15363,20 +15363,24 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
determine the address it must put in the global offset table, so
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- s = globals->root.sdynbss;
- BFD_ASSERT (s != NULL);
-
/* If allowed, we must generate a R_ARM_COPY reloc to tell the dynamic
linker to copy the initial value out of the dynamic object and into
the runtime process image. We need to remember the offset into the
.rel(a).bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = globals->root.sdynrelro;
+ srel = globals->root.sreldynrelro;
+ }
+ else
+ {
+ s = globals->root.sdynbss;
+ srel = globals->root.srelbss;
+ }
if (info->nocopyreloc == 0
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& h->size != 0)
{
- asection *srel;
-
- srel = bfd_get_linker_section (dynobj, RELOC_SECTION (globals, ".bss"));
elf32_arm_allocate_dynrelocs (info, srel, 1);
h->needs_copy = 1;
}
@@ -16091,7 +16095,8 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
&& s != htab->root.sgotplt
&& s != htab->root.iplt
&& s != htab->root.igotplt
- && s != htab->root.sdynbss)
+ && s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -16301,14 +16306,15 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));

- s = htab->root.srelbss;
- BFD_ASSERT (s != NULL);
-
rel.r_addend = 0;
rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_COPY);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
elf32_arm_add_dynreloc (output_bfd, info, s, &rel);
}

@@ -19389,6 +19395,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 1
#define elf_backend_may_use_rela_p 0
#define elf_backend_default_use_rela_p 0
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 3ce4b92..cbe42cf 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -1793,7 +1793,7 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *eh)
{
struct elf32_hppa_link_hash_table *htab;
- asection *sec;
+ asection *sec, *srel;

/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later. */
@@ -1899,14 +1899,22 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ sec = htab->etab.sdynrelro;
+ srel = htab->etab.sreldynrelro;
+ }
+ else
+ {
+ sec = htab->etab.sdynbss;
+ srel = htab->etab.srelbss;
+ }
if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0 && eh->size != 0)
{
- htab->etab.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
eh->needs_copy = 1;
}

- sec = htab->etab.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, eh, sec);
}

@@ -2374,7 +2382,8 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
}
else if (sec == htab->etab.sgot
- || sec == htab->etab.sdynbss)
+ || sec == htab->etab.sdynbss
+ || sec == htab->etab.sdynrelro)
;
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, sec), ".rela"))
{
@@ -4427,13 +4436,15 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
|| eh->root.type == bfd_link_hash_defweak)))
abort ();

- sec = htab->etab.srelbss;
-
rela.r_offset = (eh->root.u.def.value
+ eh->root.u.def.section->output_offset
+ eh->root.u.def.section->output_section->vma);
rela.r_addend = 0;
rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_COPY);
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ sec = htab->etab.sreldynrelro;
+ else
+ sec = htab->etab.srelbss;
loc = sec->contents + sec->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -4641,6 +4652,7 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_dtrel_excludes_plt 1

diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb287a8..8f4477d 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2424,7 +2424,7 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_i386_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
struct elf_i386_link_hash_entry *eh;
struct elf_dyn_relocs *p;

@@ -2584,14 +2584,22 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_386_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rel);
+ srel->size += sizeof (Elf32_External_Rel);
h->needs_copy = 1;
}

- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

@@ -3405,7 +3413,8 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
|| s == htab->elf.igotplt
|| s == htab->plt_got
|| s == htab->plt_eh_frame
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip these too. */
}
@@ -5564,20 +5573,26 @@ do_glob_dat:
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *s;

/* This symbol needs a copy reloc. Set it up. */

if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();

rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY);
- elf_append_rel (output_bfd, htab->elf.srelbss, &rel);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ elf_append_rel (output_bfd, s, &rel);
}

return TRUE;
@@ -6028,6 +6043,7 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
#define elf_backend_dtrel_excludes_plt 1
#define elf_backend_extern_protected_data 1
#define elf_backend_caches_rawsize 1
+#define elf_backend_want_dynrelro 1

/* Support RELA for objdump of prelink objects. */
#define elf_info_to_howto elf_i386_info_to_howto_rel
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 4ec2266..f4b1e12 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -2470,7 +2470,7 @@ elf_metag_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_metag_link_hash_table *htab;
struct elf_metag_link_hash_entry *hh;
struct elf_metag_dyn_reloc_entry *hdh_p;
- asection *s;
+ asection *s, *srel;

/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later,
@@ -2564,14 +2564,22 @@ elf_metag_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->etab.sdynrelro;
+ srel = htab->etab.sreldynrelro;
+ }
+ else
+ {
+ s = htab->etab.sdynbss;
+ srel = htab->etab.srelbss;
+ }
if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0 && eh->size != 0)
{
- htab->etab.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
eh->needs_copy = 1;
}

- s = htab->etab.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, eh, s);
}

@@ -2933,7 +2941,8 @@ elf_metag_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (s == htab->etab.splt
|| s == htab->etab.sgot
|| s == htab->etab.sgotplt
- || s == htab->etab.sdynbss)
+ || s == htab->etab.sdynbss
+ || s == htab->etab.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -3215,13 +3224,15 @@ elf_metag_finish_dynamic_symbol (bfd *output_bfd,
|| eh->root.type == bfd_link_hash_defweak)))
abort ();

- s = htab->etab.srelbss;
-
rel.r_offset = (eh->root.u.def.value
+ eh->root.u.def.section->output_offset
+ eh->root.u.def.section->output_section->vma);
rel.r_addend = 0;
rel.r_info = ELF32_R_INFO (eh->dynindx, R_METAG_COPY);
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->etab.sreldynrelro;
+ else
+ s = htab->etab.srelbss;
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
}
@@ -4286,6 +4297,7 @@ elf_metag_plt_sym_val (bfd_vma i, const asection *plt,
#define elf_backend_want_plt_sym 0
#define elf_backend_plt_readonly 1
#define elf_backend_dtrel_excludes_plt 1
+#define elf_backend_want_dynrelro 1

#define bfd_elf32_bfd_reloc_type_lookup metag_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup metag_reloc_name_lookup
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index 33c6026..31527d5 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -2557,9 +2557,8 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf32_mb_link_hash_table *htab;
struct elf32_mb_link_hash_entry * eh;
struct elf32_mb_dyn_relocs *p;
- asection *sdynbss, *s;
+ asection *s, *srel;
unsigned int power_of_two;
- bfd *dynobj;

htab = elf32_mb_hash_table (info);
if (htab == NULL)
@@ -2658,11 +2657,19 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}

@@ -2672,21 +2679,20 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
if (power_of_two > 3)
power_of_two = 3;

- sdynbss = htab->elf.sdynbss;
/* Apply the required alignment. */
- sdynbss->size = BFD_ALIGN (sdynbss->size, (bfd_size_type) (1 << power_of_two));
- if (power_of_two > bfd_get_section_alignment (dynobj, sdynbss))
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > s->alignment_power)
{
- if (! bfd_set_section_alignment (dynobj, sdynbss, power_of_two))
+ if (!bfd_set_section_alignment (s->owner, s, power_of_two))
return FALSE;
}

/* Define the symbol as being at this point in the section. */
- h->root.u.def.section = sdynbss;
- h->root.u.def.value = sdynbss->size;
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;

/* Increment the section size to make room for the symbol. */
- sdynbss->size += h->size;
+ s->size += h->size;
return TRUE;
}

@@ -3050,7 +3056,9 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
else if (s != htab->elf.splt
&& s != htab->elf.sgot
- && s != htab->elf.sgotplt)
+ && s != htab->elf.sgotplt
+ && s != htab->elf.sdynbss
+ && s != htab->elf.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -3256,14 +3264,15 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,

BFD_ASSERT (h->dynindx != -1);

- s = bfd_get_linker_section (htab->elf.dynobj, ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -3439,6 +3448,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
#define elf_backend_want_got_plt 1
#define elf_backend_plt_readonly 1
#define elf_backend_got_header_size 12
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_dtrel_excludes_plt 1

diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index d398810..f7649eb 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2482,6 +2482,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap

#define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 1
#define elf_backend_may_use_rela_p 0
#define elf_backend_default_use_rela_p 0
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index a4ce99c..541eb6f 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -5275,14 +5275,16 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd,
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));

- s = htab->root.srelbss;
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
+ BFD_ASSERT (s != NULL);
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -5441,7 +5443,7 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info,
{
struct elf32_nios2_link_hash_table *htab;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;
unsigned align2;

htab = elf32_nios2_hash_table (info);
@@ -5523,19 +5525,22 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info,
determine the address it must put in the global offset table, so
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- s = htab->root.sdynbss;
- BFD_ASSERT (s != NULL);
-
/* We must generate a R_NIOS2_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
{
- asection *srel;
-
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
srel = htab->root.srelbss;
- BFD_ASSERT (srel != NULL);
+ }
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
@@ -5975,7 +5980,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
of the dynobj section names depend upon the input files. */
name = bfd_get_section_name (dynobj, s);

- if (strcmp (name, ".plt") == 0)
+ if (s == htab->root.splt)
{
/* Remember whether there is a PLT. */
plt = s->size != 0;
@@ -5998,9 +6003,14 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
s->reloc_count = 0;
}
}
- else if (CONST_STRNEQ (name, ".got"))
- got = s->size != 0;
- else if (strcmp (name, ".dynbss") != 0)
+ else if (s == htab->root.sgot
+ || s == htab->root.sgotplt)
+ {
+ if (s->size != 0)
+ got = TRUE;
+ }
+ else if (s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
/* It's not one of our sections, so don't allocate space. */
continue;

@@ -6249,6 +6259,7 @@ const struct bfd_elf_special_section elf32_nios2_special_sections[] =
#define elf_backend_can_refcount 1
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_dtrel_excludes_plt 1

diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c
index c75a2ce..7fc6b81 100644
--- a/bfd/elf32-or1k.c
+++ b/bfd/elf32-or1k.c
@@ -1944,17 +1944,16 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));

- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_OR1K_COPY);
rela.r_addend = 0;
- loc = s->contents;
- loc += s->reloc_count * sizeof (Elf32_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
+ loc = s->contents + s->reloc_count * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
++s->reloc_count;
}
@@ -1995,7 +1994,7 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_or1k_link_hash_entry *eh;
struct elf_or1k_dyn_relocs *p;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;

dynobj = elf_hash_table (info)->dynobj;

@@ -2098,19 +2097,22 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
if (htab == NULL)
return FALSE;

- s = htab->root.sdynbss;
- BFD_ASSERT (s != NULL);
-
/* We must generate a R_OR1K_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
{
- asection *srel;
-
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
srel = htab->root.srelbss;
- BFD_ASSERT (srel != NULL);
+ }
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
+ {
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
@@ -2472,7 +2474,8 @@ or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (s == htab->root.splt
|| s == htab->root.sgot
|| s == htab->root.sgotplt
- || s == htab->root.sdynbss)
+ || s == htab->root.sdynbss
+ || s == htab->root.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -2742,6 +2745,7 @@ elf32_or1k_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
#define elf_backend_dtrel_excludes_plt 1
+#define elf_backend_want_dynrelro 1

#define bfd_elf32_bfd_link_hash_table_create or1k_elf_link_hash_table_create
#define elf_backend_copy_indirect_symbol or1k_elf_copy_indirect_symbol
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 7f541d1..e65ff61 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -5806,6 +5806,8 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,

if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->dynsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sdynrelro;
else
s = htab->elf.sdynbss;
BFD_ASSERT (s != NULL);
@@ -5820,6 +5822,8 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,

if (ppc_elf_hash_entry (h)->has_sda_refs)
srel = htab->relsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->elf.sreldynrelro;
else
srel = htab->elf.srelbss;
BFD_ASSERT (srel != NULL);
@@ -6636,6 +6640,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|| s == htab->elf.sgotplt
|| s == htab->sbss
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->dynsbss)
{
/* Strip these too. */
@@ -10356,6 +10361,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,

if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->relsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
else
s = htab->elf.srelbss;
BFD_ASSERT (s != NULL);
@@ -10893,6 +10900,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
#endif

#define elf_backend_plt_not_loaded 1
+#define elf_backend_want_dynrelro 1
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_rela_normal 1
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index 79c4050..b52144a 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -1607,7 +1607,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_s390_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;

/* STT_GNU_IFUNC symbol must go through PLT. */
if (s390_is_ifunc_symbol_p (h))
@@ -1757,14 +1757,22 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_390_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}

- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

@@ -2157,6 +2165,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->irelifunc)
@@ -3800,6 +3809,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
bfd_byte *loc;

/* This symbols needs a copy reloc. Set it up. */
@@ -3807,7 +3817,8 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();

rela.r_offset = (h->root.u.def.value
@@ -3815,8 +3826,11 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_390_COPY);
rela.r_addend = 0;
- loc = htab->elf.srelbss->contents;
- loc += htab->elf.srelbss->reloc_count++ * sizeof (Elf32_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}

@@ -4154,6 +4168,7 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
#define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1

#define elf_info_to_howto elf_s390_info_to_howto
diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c
index 528cba2..8610945 100644
--- a/bfd/elf32-sparc.c
+++ b/bfd/elf32-sparc.c
@@ -245,6 +245,7 @@ elf32_sparc_add_symbol_hook (bfd * abfd,
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 4
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1

#define elf_backend_add_symbol_hook elf32_sparc_add_symbol_hook
diff --git a/bfd/elf32-tic6x.c b/bfd/elf32-tic6x.c
index c2b22ee..1ccbf9c 100644
--- a/bfd/elf32-tic6x.c
+++ b/bfd/elf32-tic6x.c
@@ -1860,13 +1860,15 @@ elf32_tic6x_finish_dynamic_symbol (bfd * output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *s;

/* This symbol needs a copy reloc. Set it up. */

if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();

rel.r_offset = (h->root.u.def.value
@@ -1874,8 +1876,12 @@ elf32_tic6x_finish_dynamic_symbol (bfd * output_bfd,
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_C6000_COPY);
rel.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;

- elf32_tic6x_install_rela (output_bfd, htab->elf.srelbss, &rel);
+ elf32_tic6x_install_rela (output_bfd, s, &rel);
}

/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
@@ -2061,7 +2067,7 @@ elf32_tic6x_adjust_dynamic_symbol (struct bfd_link_info *info,
{
struct elf32_tic6x_link_hash_table *htab;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;

dynobj = elf_hash_table (info)->dynobj;

@@ -2146,14 +2152,22 @@ elf32_tic6x_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_C6000_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}

- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

@@ -3376,7 +3390,8 @@ elf32_tic6x_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
else if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -4369,6 +4384,7 @@ elf32_tic6x_write_section (bfd *output_bfd,
#define elf_backend_can_refcount 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_dynbss 1
+#define elf_backend_want_dynrelro 1
#define elf_backend_plt_readonly 1
#define elf_backend_rela_normal 1
#define elf_backend_got_header_size 8
diff --git a/bfd/elf32-tilegx.c b/bfd/elf32-tilegx.c
index bf1ad6b..1b4aa8f 100644
--- a/bfd/elf32-tilegx.c
+++ b/bfd/elf32-tilegx.c
@@ -128,6 +128,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
#define elf_backend_plt_alignment 6
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 4
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0

diff --git a/bfd/elf32-tilepro.c b/bfd/elf32-tilepro.c
index 18aabb0..f95cd27 100644
--- a/bfd/elf32-tilepro.c
+++ b/bfd/elf32-tilepro.c
@@ -2062,7 +2062,7 @@ tilepro_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct tilepro_elf_link_hash_table *htab;
struct tilepro_elf_link_hash_entry * eh;
struct tilepro_elf_dyn_relocs *p;
- asection *s;
+ asection *s, *srel;

htab = tilepro_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -2164,13 +2164,23 @@ tilepro_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += TILEPRO_ELF_RELA_BYTES;
+ srel->size += TILEPRO_ELF_RELA_BYTES;
h->needs_copy = 1;
}

- return _bfd_elf_adjust_dynamic_copy (info, h, htab->elf.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

/* Allocate space in .plt, .got and associated reloc sections for
@@ -2565,7 +2575,8 @@ tilepro_elf_size_dynamic_sections (bfd *output_bfd,
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -3797,14 +3808,15 @@ tilepro_elf_finish_dynamic_symbol (bfd *output_bfd,
/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);

- s = htab->elf.srelbss;
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_TILEPRO_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
tilepro_elf_append_rela_32 (output_bfd, s, &rela);
}

@@ -4045,6 +4057,7 @@ tilepro_additional_program_headers (bfd *abfd,
#define elf_backend_plt_alignment 6
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size GOT_ENTRY_SIZE
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0

diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index 8cd0a73..1a39522 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -4467,6 +4467,7 @@ const struct elf_size_info mips_elf64_size_info =
#define elf_backend_grok_psinfo elf64_mips_grok_psinfo

#define elf_backend_got_header_size (8 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro 1

/* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
work better/work only in RELA, so we default to this. */
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index c421426..9520777 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -72,6 +72,7 @@ static bfd_vma opd_entry_value
#define elf_backend_plt_alignment 3
#define elf_backend_plt_not_loaded 1
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_rela_normal 1
@@ -7235,7 +7236,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct ppc_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;

htab = ppc_hash_table (info);
if (htab == NULL)
@@ -7365,14 +7366,22 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf64_External_Rela);
+ srel->size += sizeof (Elf64_External_Rela);
h->needs_copy = 1;
}

- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

@@ -10174,7 +10183,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|| s == htab->elf.splt
|| s == htab->elf.iplt
|| s == htab->glink
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -10227,7 +10237,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
but this way if it does we get a R_PPC64_NONE reloc in .rela
sections instead of garbage.
We also rely on the section contents being zero when writing
- the GOT. */
+ the GOT and .dynrelro. */
s->contents = bfd_zalloc (dynobj, s->size);
if (s->contents == NULL)
return FALSE;
@@ -15421,11 +15431,13 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
/* This symbol needs a copy reloc. Set it up. */
+ asection *srel;

if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();

rela.r_offset = (h->root.u.def.value
@@ -15433,8 +15445,12 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.section->output_offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY);
rela.r_addend = 0;
- loc = htab->elf.srelbss->contents;
- loc += htab->elf.srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->elf.sreldynrelro;
+ else
+ srel = htab->elf.srelbss;
+ loc = srel->contents;
+ loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}

diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index ab2bbaa..64a74c5 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -1541,7 +1541,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_s390_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;

/* STT_GNU_IFUNC symbol must go through PLT. */
if (s390_is_ifunc_symbol_p (h))
@@ -1693,14 +1693,22 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_390_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf64_External_Rela);
+ srel->size += sizeof (Elf64_External_Rela);
h->needs_copy = 1;
}

- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

@@ -2099,6 +2107,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->irelifunc)
@@ -3585,6 +3594,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
bfd_byte *loc;

/* This symbols needs a copy reloc. Set it up. */
@@ -3600,8 +3610,11 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.section->output_offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_COPY);
rela.r_addend = 0;
- loc = htab->elf.srelbss->contents;
- loc += htab->elf.srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ loc = s->contents + s->reloc_count++ * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}

@@ -3979,6 +3992,7 @@ const struct elf_size_info s390_elf64_size_info =
#define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 24
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1

#define elf_info_to_howto elf_s390_info_to_howto
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index 65fb5e4..eecccd1 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -920,6 +920,7 @@ const struct elf_size_info elf64_sparc_size_info =
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1

/* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */
diff --git a/bfd/elf64-tilegx.c b/bfd/elf64-tilegx.c
index c281474..f3f9076 100644
--- a/bfd/elf64-tilegx.c
+++ b/bfd/elf64-tilegx.c
@@ -129,6 +129,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
#define elf_backend_plt_alignment 6
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0

diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index d5a36bc..5b3dd8a 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2828,7 +2828,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_x86_64_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
struct elf_x86_64_link_hash_entry *eh;
struct elf_dyn_relocs *p;

@@ -2986,16 +2986,24 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
const struct elf_backend_data *bed;
bed = get_elf_backend_data (info->output_bfd);
- htab->elf.srelbss->size += bed->s->sizeof_rela;
+ srel->size += bed->s->sizeof_rela;
h->needs_copy = 1;
}

- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

@@ -3811,7 +3819,8 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
|| s == htab->plt_bnd
|| s == htab->plt_got
|| s == htab->plt_eh_frame
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -6024,13 +6033,15 @@ do_glob_dat:
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;

/* This symbol needs a copy reloc. Set it up. */

if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();

rela.r_offset = (h->root.u.def.value
@@ -6038,7 +6049,11 @@ do_glob_dat:
+ h->root.u.def.section->output_offset);
rela.r_info = htab->r_info (h->dynindx, R_X86_64_COPY);
rela.r_addend = 0;
- elf_append_rela (output_bfd, htab->elf.srelbss, &rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ elf_append_rela (output_bfd, s, &rela);
}

return TRUE;
@@ -6719,6 +6734,7 @@ static const struct bfd_elf_special_section
#define elf_backend_extern_protected_data 1
#define elf_backend_caches_rawsize 1
#define elf_backend_dtrel_excludes_plt 1
+#define elf_backend_want_dynrelro 1

#define elf_info_to_howto elf_x86_64_info_to_howto

diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9728e29..d8d40f1 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -429,6 +429,19 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
return FALSE;
htab->sdynbss = s;

+ if (bed->want_dynrelro)
+ {
+ /* Similarly, but for symbols that were originally in read-only
+ sections. */
+ s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro",
+ (SEC_ALLOC | SEC_READONLY
+ | SEC_HAS_CONTENTS
+ | SEC_LINKER_CREATED));
+ if (s == NULL)
+ return FALSE;
+ htab->sdynrelro = s;
+ }
+
/* The .rel[a].bss section holds copy relocs. This section is not
normally needed. We need to create it here, though, so that the
linker will map it to an output section. We can't just create it
@@ -450,6 +463,19 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
htab->srelbss = s;
+
+ if (bed->want_dynrelro)
+ {
+ s = (bfd_make_section_anyway_with_flags
+ (abfd, (bed->rela_plts_and_copies_p
+ ? ".rela.data.rel.ro" : ".rel.data.rel.ro"),
+ flags | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s,
+ bed->s->log_file_align))
+ return FALSE;
+ htab->sreldynrelro = s;
+ }
}
}

diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 8a55596..0103b01 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -6833,7 +6833,7 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_aarch64_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;

/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later,
@@ -6910,14 +6910,22 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_AARCH64_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
+ srel = htab->root.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->root.srelbss->size += RELOC_SIZE (htab);
+ srel->size += RELOC_SIZE (htab);
h->needs_copy = 1;
}

- s = htab->root.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);

}
@@ -8517,7 +8525,8 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|| s == htab->root.sgotplt
|| s == htab->root.iplt
|| s == htab->root.igotplt
- || s == htab->root.sdynbss)
+ || s == htab->root.sdynbss
+ || s == htab->root.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -8921,6 +8930,7 @@ do_glob_dat:
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
bfd_byte *loc;

/* This symbol needs a copy reloc. Set it up. */
@@ -8936,8 +8946,11 @@ do_glob_dat:
+ h->root.u.def.section->output_offset);
rela.r_info = ELFNN_R_INFO (h->dynindx, AARCH64_R (COPY));
rela.r_addend = 0;
- loc = htab->root.srelbss->contents;
- loc += htab->root.srelbss->reloc_count++ * RELOC_SIZE (htab);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
+ loc = s->contents + s->reloc_count++ * RELOC_SIZE (htab);
bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc);
}

@@ -9390,6 +9403,7 @@ const struct elf_size_info elfNN_aarch64_size_info =
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 0
#define elf_backend_may_use_rela_p 1
#define elf_backend_default_use_rela_p 1
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index db4b782..69907bd 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -862,7 +862,7 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct riscv_elf_link_hash_entry * eh;
struct riscv_elf_dyn_relocs *p;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;

htab = riscv_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -965,16 +965,26 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (ElfNN_External_Rela);
+ srel->size += sizeof (ElfNN_External_Rela);
h->needs_copy = 1;
}

if (eh->tls_type & ~GOT_NORMAL)
return _bfd_elf_adjust_dynamic_copy (info, h, htab->sdyntdata);

- return _bfd_elf_adjust_dynamic_copy (info, h, htab->elf.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

/* Allocate space in .plt, .got and associated reloc sections for
@@ -1328,7 +1338,8 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -2389,6 +2400,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;

/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);
@@ -2396,7 +2408,11 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value;
rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_COPY);
rela.r_addend = 0;
- riscv_elf_append_rela (output_bfd, htab->elf.srelbss, &rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ riscv_elf_append_rela (output_bfd, s, &rela);
}

/* Mark some specially defined symbols as absolute. */
@@ -3213,6 +3229,7 @@ riscv_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
#define elf_backend_plt_alignment 4
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size (ARCH_SIZE / 8)
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0

diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 086d537..7c7cd38 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -9129,6 +9129,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
bfd *dynobj;
struct mips_elf_link_hash_entry *hmips;
struct mips_elf_link_hash_table *htab;
+ asection *s, *srel;

htab = mips_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -9371,10 +9372,20 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
both the dynamic object and the regular object will refer to the
same memory location for the variable. */

+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
+ srel = htab->root.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
if (htab->is_vxworks)
- htab->root.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
else
mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
h->needs_copy = 1;
@@ -9384,7 +9395,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
dynamic will now refer to the local copy instead. */
hmips->possibly_dynamic_relocs = 0;

- return _bfd_elf_adjust_dynamic_copy (info, h, htab->root.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

/* This function is called after all the input files have been read,
@@ -9906,7 +9917,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
&& s != htab->root.sgot
&& s != htab->root.sgotplt
&& s != htab->sstubs
- && s != htab->root.sdynbss)
+ && s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -11296,6 +11308,8 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *srel;
+ bfd_byte *loc;

BFD_ASSERT (h->dynindx != -1);

@@ -11304,11 +11318,13 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.value);
rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY);
rel.r_addend = 0;
- bfd_elf32_swap_reloca_out (output_bfd, &rel,
- htab->root.srelbss->contents
- + (htab->root.srelbss->reloc_count
- * sizeof (Elf32_External_Rela)));
- ++htab->root.srelbss->reloc_count;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->root.sreldynrelro;
+ else
+ srel = htab->root.srelbss;
+ loc = srel->contents + srel->reloc_count * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+ ++srel->reloc_count;
}

/* If this is a mips16/microMIPS symbol, force the value to be even. */
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 050993c..d7b2688 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -2086,7 +2086,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct _bfd_sparc_elf_link_hash_table *htab;
struct _bfd_sparc_elf_link_hash_entry * eh;
struct _bfd_sparc_elf_dyn_relocs *p;
- asection *s;
+ asection *s, *srel;

htab = _bfd_sparc_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -2199,14 +2199,22 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += SPARC_ELF_RELA_BYTES (htab);
+ srel->size += SPARC_ELF_RELA_BYTES (htab);
h->needs_copy = 1;
}

- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

@@ -2686,6 +2694,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->elf.iplt
|| s == htab->elf.sgotplt)
{
@@ -4527,15 +4536,15 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);

- s = bfd_get_linker_section (h->root.u.def.section->owner,
- ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
sparc_elf_append_rela (output_bfd, s, &rela);
}

diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index aff8621..7f08128 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -108,6 +108,9 @@
#ifndef elf_backend_want_dynbss
#define elf_backend_want_dynbss 1
#endif
+#ifndef elf_backend_want_dynrelro
+#define elf_backend_want_dynrelro 0
+#endif
#ifndef elf_backend_want_p_paddr_set_to_zero
#define elf_backend_want_p_paddr_set_to_zero 0
#endif
@@ -855,6 +858,7 @@ static struct elf_backend_data elfNN_bed =
elf_backend_can_refcount,
elf_backend_want_got_sym,
elf_backend_want_dynbss,
+ elf_backend_want_dynrelro,
elf_backend_want_p_paddr_set_to_zero,
elf_backend_default_execstack,
elf_backend_caches_rawsize,
diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c
index 92b9de8..ce4fb07 100644
--- a/bfd/elfxx-tilegx.c
+++ b/bfd/elfxx-tilegx.c
@@ -2327,7 +2327,7 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct tilegx_elf_link_hash_entry * eh;
struct tilegx_elf_dyn_relocs *p;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;

htab = tilegx_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -2431,13 +2431,23 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += TILEGX_ELF_RELA_BYTES (htab);
+ srel->size += TILEGX_ELF_RELA_BYTES (htab);
h->needs_copy = 1;
}

- return _bfd_elf_adjust_dynamic_copy (info, h, htab->elf.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}

/* Allocate space in .plt, .got and associated reloc sections for
@@ -2826,7 +2836,8 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -4187,7 +4198,10 @@ tilegx_elf_finish_dynamic_symbol (bfd *output_bfd,
/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);

- s = htab->elf.srelbss;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
BFD_ASSERT (s != NULL);

rela.r_offset = (h->root.u.def.value
diff --git a/ld/testsuite/ld-arm/farcall-mixed-app-v5.d b/ld/testsuite/ld-arm/farcall-mixed-app-v5.d
index b570bad..af44198 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-app-v5.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-app-v5.d
@@ -50,8 +50,8 @@ Disassembly of section .far_arm:
.* <app_func>:
.*: e1a0c00d mov ip, sp
.*: e92dd800 push {fp, ip, lr, pc}
- .*: eb0000.. bl .* <__lib_func1_veneer>
- .*: eb0000.. bl .* <__lib_func2_veneer>
+ .*: eb00000(6|8) bl .* <__lib_func1_veneer>
+ .*: eb00000(7|5) bl .* <__lib_func2_veneer>
.*: e89d6800 ldm sp, {fp, sp, lr}
.*: e12fff1e bx lr
.*: e1a00000 nop ; \(mov r0, r0\)
@@ -61,12 +61,12 @@ Disassembly of section .far_arm:
.*: e12fff1e bx lr
#...

-.* <__lib_func1_veneer>:
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func1_veneer\+0x4>
- .*: 000081e8 .word 0x000081e8
-.* <__lib_func2_veneer>:
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func2_veneer\+0x4>
- .*: 000081dc .word 0x000081dc
+.* <__lib_func(1|2)_veneer>:
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(1|2)_veneer\+0x4>
+ .*: 000081(e8|dc) .word 0x000081(e8|dc)
+.* <__lib_func(2|1)_veneer>:
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(2|1)_veneer\+0x4>
+ .*: 000081(dc|e8) .word 0x000081(dc|e8)

Disassembly of section .far_thumb:

diff --git a/ld/testsuite/ld-arm/farcall-mixed-app.d b/ld/testsuite/ld-arm/farcall-mixed-app.d
index 9fa97dc..f3be54f 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-app.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-app.d
@@ -52,8 +52,8 @@ Disassembly of section .far_arm:
.* <app_func>:
.*: e1a0c00d mov ip, sp
.*: e92dd800 push {fp, ip, lr, pc}
- .*: eb000006 bl .* <__lib_func1_veneer>
- .*: eb000007 bl .* <__lib_func2_veneer>
+ .*: eb00000(6|8) bl .* <__lib_func1_veneer>
+ .*: eb00000(7|5) bl .* <__lib_func2_veneer>
.*: e89d6800 ldm sp, {fp, sp, lr}
.*: e12fff1e bx lr
.*: e1a00000 nop ; \(mov r0, r0\)
@@ -63,12 +63,12 @@ Disassembly of section .far_arm:
.*: e12fff1e bx lr
#...

-.* <__lib_func1_veneer>:
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func1_veneer\+0x4>
- .*: 000081ec .word 0x000081ec
-.* <__lib_func2_veneer>:
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func2_veneer\+0x4>
- .*: 000081e0 .word 0x000081e0
+.* <__lib_func(1|2)_veneer>:
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(1|2)_veneer\+0x4>
+ .*: 000081e(c|0) .word 0x000081e(c|0)
+.* <__lib_func(2|1)_veneer>:
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(2|1)_veneer\+0x4>
+ .*: 000081e(0|c) .word 0x000081e(0|c)

Disassembly of section .far_thumb:

diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d b/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d
index fa52ad1..83b15a0 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d
@@ -87,24 +87,24 @@ Disassembly of section .text:
...

.* <__real_lib_func3>:
- .*: f000 f80e bl 2000390 <__app_func_from_thumb>
- .*: f000 f804 bl 2000380 <__app_func_weak_from_thumb>
+ .*: f000 f80(e|6) bl .* <__app_func_from_thumb>
+ .*: f000 f80(4|c) bl .* <__app_func_weak_from_thumb>
.*: 4770 bx lr
#...

-.* <__app_func_weak_from_thumb>:
+.* <__app_func(_weak)?_from_thumb>:
.*: 4778 bx pc
.*: 46c0 nop ; \(mov r8, r8\)
- .*: e59fc000 ldr ip, \[pc\] ; 200038c <__app_func_weak_from_thumb\+0xc>
+ .*: e59fc000 ldr ip, \[pc\] ; 200038c <__app_func(_weak)?_from_thumb\+0xc>
.*: e08cf00f add pc, ip, pc
- .*: fdffff28 .word 0xfdffff28
+ .*: fdffff(2|1)8 .word 0xfdffff(2|1)8

-.* <__app_func_from_thumb>:
+.* <__app_func(_weak)?_from_thumb>:
.*: 4778 bx pc
.*: 46c0 nop ; \(mov r8, r8\)
- .*: e59fc000 ldr ip, \[pc\] ; 200039c <__app_func_from_thumb\+0xc>
+ .*: e59fc000 ldr ip, \[pc\] ; 200039c <__app_func(_weak)?_from_thumb\+0xc>
.*: e08cf00f add pc, ip, pc
- .*: fdffff08 .word 0xfdffff08
+ .*: fdffff(0|1)8 .word 0xfdffff(0|1)8

.* <lib_func3>:
.*: e59fc004 ldr ip, \[pc, #4\] ; 20003ac <lib_func3\+0xc>
diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib.d b/ld/testsuite/ld-arm/farcall-mixed-lib.d
index ad7352b..d256477 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-lib.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-lib.d
@@ -72,18 +72,18 @@ Disassembly of section .text:
...

.* <lib_func3>:
- .*: f000 e80c blx 200037c <__app_func_from_thumb>
- .*: f000 e804 blx 2000370 <__app_func_weak_from_thumb>
+ .*: f000 e80(c|6) blx .* <__app_func_from_thumb>
+ .*: f000 e80(4|a) blx .* <__app_func_weak_from_thumb>
.*: 4770 bx lr
#...

-.* <__app_func_weak_from_thumb>:
- .*: e59fc000 ldr ip, \[pc\] ; 2000378 <__app_func_weak_from_thumb\+0x8>
+.* <__app_func(_weak)?_from_thumb>:
+ .*: e59fc000 ldr ip, \[pc\] ; 2000378 <__app_func(_weak)?_from_thumb\+0x8>
.*: e08ff00c add pc, pc, ip
- .*: fdffff34 .word 0xfdffff34
+ .*: fdffff(34|28) .word 0xfdffff(34|28)

-.* <__app_func_from_thumb>:
- .*: e59fc000 ldr ip, \[pc\] ; 2000384 <__app_func_from_thumb\+0x8>
+.* <__app_func(_weak)?_from_thumb>:
+ .*: e59fc000 ldr ip, \[pc\] ; 2000384 <__app_func(_weak)?_from_thumb\+0x8>
.*: e08ff00c add pc, pc, ip
- .*: fdffff1c .word 0xfdffff1c
+ .*: fdffff(1c|28) .word 0xfdffff(1c|28)
...
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index f93ad46..9b1fbeb 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -127,6 +127,20 @@ if { [check_shared_lib_support] } then {
{symbolic-func.s} {{readelf {-r --wide} symbolic-func.r}}
"symbolic-func.so"}
}
+ # xfail on tic6x due to non-PIC/non-PID warnings
+ setup_xfail "tic6x-*-*"
+ run_ld_link_tests {
+ {"Build pr20995.so"
+ "-shared" "" ""
+ {pr20995b.s} {} "pr20995.so"}
+ }
+ # These targets don't copy dynamic variables into .bss.
+ setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*"
+ run_ld_link_tests {
+ {"pr20995"
+ "" "tmpdir/pr20995.so" ""
+ {pr20995a.s} {{readelf {-S --wide} pr20995.r}} "pr20995"}
+ }
}

set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
diff --git a/ld/testsuite/ld-elf/pr20995.r b/ld/testsuite/ld-elf/pr20995.r
new file mode 100644
index 0000000..7336de6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr20995.r
@@ -0,0 +1,5 @@
+#...
+.* \.data\.rel\.ro +PROGBITS +[^ ]+ [^ ]+ [^ ]*[1-9a-f]0* .*
+#...
+.* \.bss +NOBITS +[^ ]+ [^ ]+ [^ ]*[1-9a-f]0* .*
+#...
diff --git a/ld/testsuite/ld-elf/pr20995a.s b/ld/testsuite/ld-elf/pr20995a.s
new file mode 100644
index 0000000..8da589c
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr20995a.s
@@ -0,0 +1,11 @@
+ .text
+ .global start
+start:
+ .global _start
+_start:
+ .global __start
+__start:
+ .global main
+main:
+ .dc.a rw
+ .dc.a ro
diff --git a/ld/testsuite/ld-elf/pr20995b.s b/ld/testsuite/ld-elf/pr20995b.s
new file mode 100644
index 0000000..7ff76ee
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr20995b.s
@@ -0,0 +1,13 @@
+ .data
+ .type rw,%object
+ .globl rw
+rw:
+ .dc.a 0
+ .size rw, . - rw
+
+ .text
+ .type ro,%object
+ .globl ro
+ro:
+ .dc.a 0
+ .size ro, . - ro
--
Alan Modra
Australia Development Lab, IBM
Cary Coutant
2016-12-28 04:55:33 UTC
Permalink
Post by Alan Modra
Variables defined in shared libraries are copied into an executable's
.bss section when code in the executable is non-PIC and thus would
require dynamic text relocations to access the variable directly in
the shared library. Recent x86 toolchains also copy variables into
the executable to gain a small speed improvement.
The problem is that if the variable was originally read-only, the copy
in .bss is writable, potentially opening a security hole. This patch
cures that problem by putting the copy in a section that becomes
read-only after ld.so relocation, provided -z relro is in force.
It doesn't look like you caught the case where the original variable
is in the .data.rel.ro section (which is marked SHF_WRITE initially,
but placed in the PT_GNU_RELRO segment). These variables should also
be copied to .data.rel.ro in the main executable.

I've just committed a gold patch for this. To identify relro
variables, I checked the section name (ugly) -- I considered checking
the virtual address against the bounds of PT_GNU_RELRO, but that
wasn't really efficient.

I wish we had an SHF_RELRO flag.

-cary
Alan Modra
2016-12-28 06:50:46 UTC
Permalink
This post might be inappropriate. Click to display it.
Palmer Dabbelt
2016-12-29 18:20:06 UTC
Permalink
Post by Alan Modra
riscv scripts are hosed for -z relro.
Andrew and I can't figure out why relro is broken on RISC-V. I looked at our
linker scripts (via riscv64-unknown-linux-gnu-gcc -Wl,-verbose) and the .rel.ro
section looks the same as on my x86 machine, and it's in a similar order to the
x86 one (the got has moved a bit, but there's a comment for why it's in a
slightly different place). Additionally, I readelf'd some arbitrary executable
and it appears that the GNU_RELRO segment is read-only

$ riscv64-unknown-linux-gnu-readelf -l install/sysroot/usr/bin/locale

Elf file type is EXEC (Executable file)
Entry point 0x168a4
There are 9 program headers, starting at offset 64

Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000010040 0x0000000000010040
0x00000000000001f8 0x00000000000001f8 R E 0x8
INTERP 0x0000000000000238 0x0000000000010238 0x0000000000010238
0x0000000000000014 0x0000000000000014 R 0x1
[Requesting program interpreter: /lib64/lp64/ld.so.1]
LOAD 0x0000000000000000 0x0000000000010000 0x0000000000010000
0x00000000000039b4 0x00000000000039f8 RW 0x1000
LOAD 0x00000000000039f8 0x00000000000149f8 0x00000000000149f8
0x00000000000047e4 0x00000000000047e4 R E 0x1000
LOAD 0x0000000000008e00 0x000000000001ae00 0x000000000001ae00
0x0000000000000438 0x0000000000000438 RW 0x1000
DYNAMIC 0x0000000000008e20 0x000000000001ae20 0x000000000001ae20
0x00000000000001e0 0x00000000000001e0 RW 0x8
NOTE 0x000000000000024c 0x000000000001024c 0x000000000001024c
0x0000000000000020 0x0000000000000020 R 0x4
GNU_EH_FRAME 0x0000000000008194 0x0000000000019194 0x0000000000019194
0x0000000000000014 0x0000000000000014 R 0x4
GNU_RELRO 0x0000000000008e00 0x000000000001ae00 0x000000000001ae00
0x0000000000000200 0x0000000000000200 R 0x1

Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .data .rodata .sdata .sbss .bss
03 .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .plt .text .eh_frame_hdr .eh_frame
04 .preinit_array .init_array .fini_array .jcr .dynamic .got
05 .dynamic
06 .note.ABI-tag
07 .eh_frame_hdr
08 .preinit_array .init_array .fini_array .jcr .dynamic

I saw your metage relro patch go by, but we have COMMONPAGESIZE so I don't
think that's the problem.

Can you (or anyone else) offer a hint? We'd love to get this fixed, we just
didn't know about the problem.

Thanks for the heads up!
Alan Modra
2016-12-29 22:24:02 UTC
Permalink
Post by Palmer Dabbelt
Post by Alan Modra
riscv scripts are hosed for -z relro.
Andrew and I can't figure out why relro is broken on RISC-V.
You have this at the start of your scripts.

.interp : { *(.interp) }
.data : { *(.data) *(.data.*) *(.gnu.linkonce.d.*) }
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }

So .data.rel.ro goes into .data since it matches *(.data.*). Also,
.rodata after .data is a problem. Since you don't give a page gap
between sections with differing write protection, you will make
.interp and .rodata writable. As shown below.

[snip]
Post by Palmer Dabbelt
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000010040 0x0000000000010040
0x00000000000001f8 0x00000000000001f8 R E 0x8
INTERP 0x0000000000000238 0x0000000000010238 0x0000000000010238
0x0000000000000014 0x0000000000000014 R 0x1
[Requesting program interpreter: /lib64/lp64/ld.so.1]
LOAD 0x0000000000000000 0x0000000000010000 0x0000000000010000
0x00000000000039b4 0x00000000000039f8 RW 0x1000
[snip]
Post by Palmer Dabbelt
02 .interp .note.ABI-tag .data .rodata .sdata .sbss .bss
Run-time permission is determined by the PT_LOAD program header flags.
The section permissions don't matter, nor does the PT_INTERP program
header flags.
--
Alan Modra
Australia Development Lab, IBM
Palmer Dabbelt
2017-01-02 02:25:56 UTC
Permalink
Post by Alan Modra
Post by Palmer Dabbelt
Post by Alan Modra
riscv scripts are hosed for -z relro.
Andrew and I can't figure out why relro is broken on RISC-V.
You have this at the start of your scripts.
.interp : { *(.interp) }
.data : { *(.data) *(.data.*) *(.gnu.linkonce.d.*) }
.rodata : { *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) }
So .data.rel.ro goes into .data since it matches *(.data.*). Also,
.rodata after .data is a problem. Since you don't give a page gap
between sections with differing write protection, you will make
.interp and .rodata writable. As shown below.
[snip]
Post by Palmer Dabbelt
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000010040 0x0000000000010040
0x00000000000001f8 0x00000000000001f8 R E 0x8
INTERP 0x0000000000000238 0x0000000000010238 0x0000000000010238
0x0000000000000014 0x0000000000000014 R 0x1
[Requesting program interpreter: /lib64/lp64/ld.so.1]
LOAD 0x0000000000000000 0x0000000000010000 0x0000000000010000
0x00000000000039b4 0x00000000000039f8 RW 0x1000
[snip]
Post by Palmer Dabbelt
02 .interp .note.ABI-tag .data .rodata .sdata .sbss .bss
Run-time permission is determined by the PT_LOAD program header flags.
The section permissions don't matter, nor does the PT_INTERP program
header flags.
Thankn! I believe we have a fix, it's in a patcheset I'm just mailing out now.
Christophe Lyon
2017-01-03 10:12:38 UTC
Permalink
Post by Alan Modra
Variables defined in shared libraries are copied into an executable's
.bss section when code in the executable is non-PIC and thus would
require dynamic text relocations to access the variable directly in
the shared library. Recent x86 toolchains also copy variables into
the executable to gain a small speed improvement.
The problem is that if the variable was originally read-only, the copy
in .bss is writable, potentially opening a security hole. This patch
cures that problem by putting the copy in a section that becomes
read-only after ld.so relocation, provided -z relro is in force.
These targets should now be OK: aarch64, arm, hppa, i386, metag,
microblaze, mips, mips64, nios2, or1k, ppc, ppc64, s390, s390x, sparc,
sparc64, tic6x, tilegx, tilepro and x86-64. However, not much testing
has been done yet.. I applied fixes for riscv too, before realizing
that riscv scripts are broken for relro.
The patch also fixes a microblaze linker segfault on attempting to
use dynamic bss variables.
am33_2.0-linux +FAIL: pr20995
For the record, I see failures on some arm targets:
FAIL: Build pr20995-2.so
FAIL: pr20995-2
for arm-netbsdelf and arm-none-eabi

The other arm targets I test are OK:
arm-linux-gnueabi
arm-linux-gnueabihf
arm-none-nacl
arm-none-symbianelf
arm-vxworks
arm-wince-pe
armeb-linux-gnueabihf

Christophe
Post by Alan Modra
arc-linux-uclibc +FAIL: pr20995
crisv32-linux +FAIL: pr20995
hppa64-hp-hpux11.23 +FAIL: pr20995
hppa64-linux +FAIL: pr20995
i370-linux +FAIL: Build pr20995.so
i370-linux +FAIL: pr20995
m68k-elf +FAIL: pr20995
m68k-linux +FAIL: pr20995
mips64-linux +FAIL: pr20995
mipsel-linux-gnu +FAIL: pr20995
mipsisa32el-linux +FAIL: pr20995
mips-linux +FAIL: pr20995
mn10300-elf +FAIL: pr20995
riscv32-elf +FAIL: pr20995
riscv64-elf +FAIL: pr20995
score-elf +FAIL: pr20995
sh-linux +FAIL: pr20995
shl-unknown-netbsdelf +FAIL: pr20995
tic6x-elf +FAIL: pr20995
vax-netbsdelf +FAIL: pr20995
mips apparently needs a tweak to run the testcase with the right
flags. riscv scripts are hosed for -z relro. tic6x doesn't want to
create any dynamic relocs for the testcase. The rest are targets that
I haven't converted over to use the new dynamic sections for read-only
variables. I don't intend to do much more on this over Christmas
and New Year, so if your favourite target is one of those that fails
the test it's likely that 2.28 will go out without the fix unless
target maintainers step up.
bfd/
PR ld/20995
* elf-bfd.h (struct elf_link_hash_table): Add sdynrelro and
sreldynrelro.
(struct elf_backend_data): Add want_dynrelro.
* elfxx-target.h (elf_backend_want_dynrelro): Define.
(elfNN_bed): Update initializer.
* elflink.c (_bfd_elf_create_dynamic_sections): Create
sdynrelro and sreldynrelro sections.
* elf32-arm.c (elf32_arm_adjust_dynamic_symbol): Place variables
copied into the executable from read-only sections into sdynrelro.
(elf32_arm_size_dynamic_sections): Handle sdynrelro.
(elf32_arm_finish_dynamic_symbol): Select sreldynrelro for
dynamic relocs in sdynrelro.
(elf_backend_want_dynrelro): Define.
* elf32-hppa.c (elf32_hppa_adjust_dynamic_symbol)
(elf32_hppa_size_dynamic_sections, elf32_hppa_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-i386.c (elf_i386_adjust_dynamic_symbol)
(elf_i386_size_dynamic_sections, elf_i386_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-metag.c (elf_metag_adjust_dynamic_symbol)
(elf_metag_size_dynamic_sections, elf_metag_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-microblaze.c (microblaze_elf_adjust_dynamic_symbol)
(microblaze_elf_size_dynamic_sections)
(microblaze_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-nios2.c (nios2_elf32_finish_dynamic_symbol)
(nios2_elf32_adjust_dynamic_symbol)
(nios2_elf32_size_dynamic_sections)
(elf_backend_want_dynrelro): As above.
* elf32-or1k.c (or1k_elf_finish_dynamic_symbol)
(or1k_elf_adjust_dynamic_symbol, or1k_elf_size_dynamic_sections)
(elf_backend_want_dynrelro): As above.
* elf32-ppc.c (ppc_elf_adjust_dynamic_symbol)
(ppc_elf_size_dynamic_sections, ppc_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-s390.c (elf_s390_adjust_dynamic_symbol)
(elf_s390_size_dynamic_sections, elf_s390_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-tic6x.c (elf32_tic6x_adjust_dynamic_symbol)
(elf32_tic6x_size_dynamic_sections)
(elf32_tic6x_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf32-tilepro.c (tilepro_elf_adjust_dynamic_symbol)
(tilepro_elf_size_dynamic_sections)
(tilepro_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol)
(ppc64_elf_size_dynamic_sections, ppc64_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf64-s390.c (elf_s390_adjust_dynamic_symbol)
(elf_s390_size_dynamic_sections, elf_s390_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elf64-x86-64.c (elf_x86_64_adjust_dynamic_symbol)
(elf_x86_64_size_dynamic_sections)
(elf_x86_64_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elfnn-aarch64.c (elfNN_aarch64_adjust_dynamic_symbol)
(elfNN_aarch64_size_dynamic_sections)
(elfNN_aarch64_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elfnn-riscv.c (riscv_elf_adjust_dynamic_symbol)
(riscv_elf_size_dynamic_sections, riscv_elf_finish_dynamic_symbol)
(elf_backend_want_dynrelro): As above.
* elfxx-mips.c (_bfd_mips_elf_adjust_dynamic_symbol)
(_bfd_mips_elf_size_dynamic_sections)
(_bfd_mips_vxworks_finish_dynamic_symbol): As above.
* elfxx-sparc.c (_bfd_sparc_elf_adjust_dynamic_symbol)
(_bfd_sparc_elf_size_dynamic_sections)
(_bfd_sparc_elf_finish_dynamic_symbol): As above.
* elfxx-tilegx.c (tilegx_elf_adjust_dynamic_symbol)
(tilegx_elf_size_dynamic_sections)
(tilegx_elf_finish_dynamic_symbol): As above.
* elf32-mips.c (elf_backend_want_dynrelro): Define.
* elf64-mips.c (elf_backend_want_dynrelro): Define.
* elf32-sparc.c (elf_backend_want_dynrelro): Define.
* elf64-sparc.c (elf_backend_want_dynrelro): Define.
* elf32-tilegx.c (elf_backend_want_dynrelro): Define.
* elf64-tilegx.c (elf_backend_want_dynrelro): Define.
* elf32-microblaze.c (microblaze_elf_adjust_dynamic_symbol): Tidy.
(microblaze_elf_size_dynamic_sections): Handle sdynbss.
* elf32-nios2.c (nios2_elf32_size_dynamic_sections): Make use
of linker shortcuts to dynamic sections rather than comparing
names. Correctly set "got" flag.
ld/
PR ld/20995
* testsuite/ld-arm/farcall-mixed-app-v5.d: Update to suit changed
stub hash table traversal caused by section id increment. Accept
the previous output too.
* testsuite/ld-arm/farcall-mixed-app.d: Likewise.
* testsuite/ld-arm/farcall-mixed-lib-v4t.d: Likewise.
* testsuite/ld-arm/farcall-mixed-lib.d: Likewise.
* testsuite/ld-elf/pr20995a.s, * testsuite/ld-elf/pr20995b.s,
* testsuite/ld-elf/pr20995.r: New test.
* testsuite/ld-elf/elf.exp: Run it.
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 4093434..1c634d8 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -597,6 +597,8 @@ struct elf_link_hash_table
asection *srelplt;
asection *sdynbss;
asection *srelbss;
+ asection *sdynrelro;
+ asection *sreldynrelro;
asection *igotplt;
asection *iplt;
asection *irelplt;
@@ -1451,6 +1453,7 @@ struct elf_backend_data
unsigned can_refcount : 1;
unsigned want_got_sym : 1;
unsigned want_dynbss : 1;
+ unsigned want_dynrelro : 1;
/* Targets which do not support physical addressing often require
that the p_paddr field in the section header to be set to zero.
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index 4761136..384063e 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -15264,7 +15264,7 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
struct elf_link_hash_entry * h)
{
bfd * dynobj;
- asection * s;
+ asection *s, *srel;
struct elf32_arm_link_hash_entry * eh;
struct elf32_arm_link_hash_table *globals;
@@ -15363,20 +15363,24 @@ elf32_arm_adjust_dynamic_symbol (struct bfd_link_info * info,
determine the address it must put in the global offset table, so
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- s = globals->root.sdynbss;
- BFD_ASSERT (s != NULL);
-
/* If allowed, we must generate a R_ARM_COPY reloc to tell the dynamic
linker to copy the initial value out of the dynamic object and into
the runtime process image. We need to remember the offset into the
.rel(a).bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = globals->root.sdynrelro;
+ srel = globals->root.sreldynrelro;
+ }
+ else
+ {
+ s = globals->root.sdynbss;
+ srel = globals->root.srelbss;
+ }
if (info->nocopyreloc == 0
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& h->size != 0)
{
- asection *srel;
-
- srel = bfd_get_linker_section (dynobj, RELOC_SECTION (globals, ".bss"));
elf32_arm_allocate_dynrelocs (info, srel, 1);
h->needs_copy = 1;
}
@@ -16091,7 +16095,8 @@ elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
&& s != htab->root.sgotplt
&& s != htab->root.iplt
&& s != htab->root.igotplt
- && s != htab->root.sdynbss)
+ && s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -16301,14 +16306,15 @@ elf32_arm_finish_dynamic_symbol (bfd * output_bfd,
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));
- s = htab->root.srelbss;
- BFD_ASSERT (s != NULL);
-
rel.r_addend = 0;
rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_ARM_COPY);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
elf32_arm_add_dynreloc (output_bfd, info, s, &rel);
}
@@ -19389,6 +19395,7 @@ elf32_arm_backend_symbol_processing (bfd *abfd, asymbol *sym)
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 1
#define elf_backend_may_use_rela_p 0
#define elf_backend_default_use_rela_p 0
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c
index 3ce4b92..cbe42cf 100644
--- a/bfd/elf32-hppa.c
+++ b/bfd/elf32-hppa.c
@@ -1793,7 +1793,7 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *eh)
{
struct elf32_hppa_link_hash_table *htab;
- asection *sec;
+ asection *sec, *srel;
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later. */
@@ -1899,14 +1899,22 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ sec = htab->etab.sdynrelro;
+ srel = htab->etab.sreldynrelro;
+ }
+ else
+ {
+ sec = htab->etab.sdynbss;
+ srel = htab->etab.srelbss;
+ }
if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0 && eh->size != 0)
{
- htab->etab.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
eh->needs_copy = 1;
}
- sec = htab->etab.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, eh, sec);
}
@@ -2374,7 +2382,8 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
}
else if (sec == htab->etab.sgot
- || sec == htab->etab.sdynbss)
+ || sec == htab->etab.sdynbss
+ || sec == htab->etab.sdynrelro)
;
else if (CONST_STRNEQ (bfd_get_section_name (dynobj, sec), ".rela"))
{
@@ -4427,13 +4436,15 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
|| eh->root.type == bfd_link_hash_defweak)))
abort ();
- sec = htab->etab.srelbss;
-
rela.r_offset = (eh->root.u.def.value
+ eh->root.u.def.section->output_offset
+ eh->root.u.def.section->output_section->vma);
rela.r_addend = 0;
rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_COPY);
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ sec = htab->etab.sreldynrelro;
+ else
+ sec = htab->etab.srelbss;
loc = sec->contents + sec->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -4641,6 +4652,7 @@ elf32_hppa_elf_get_symbol_type (Elf_Internal_Sym *elf_sym, int type)
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_dtrel_excludes_plt 1
diff --git a/bfd/elf32-i386.c b/bfd/elf32-i386.c
index eb287a8..8f4477d 100644
--- a/bfd/elf32-i386.c
+++ b/bfd/elf32-i386.c
@@ -2424,7 +2424,7 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_i386_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
struct elf_i386_link_hash_entry *eh;
struct elf_dyn_relocs *p;
@@ -2584,14 +2584,22 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_386_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rel);
+ srel->size += sizeof (Elf32_External_Rel);
h->needs_copy = 1;
}
- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -3405,7 +3413,8 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
|| s == htab->elf.igotplt
|| s == htab->plt_got
|| s == htab->plt_eh_frame
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip these too. */
}
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *s;
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();
rel.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_386_COPY);
- elf_append_rel (output_bfd, htab->elf.srelbss, &rel);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ elf_append_rel (output_bfd, s, &rel);
}
return TRUE;
@@ -6028,6 +6043,7 @@ elf_i386_hash_symbol (struct elf_link_hash_entry *h)
#define elf_backend_dtrel_excludes_plt 1
#define elf_backend_extern_protected_data 1
#define elf_backend_caches_rawsize 1
+#define elf_backend_want_dynrelro 1
/* Support RELA for objdump of prelink objects. */
#define elf_info_to_howto elf_i386_info_to_howto_rel
diff --git a/bfd/elf32-metag.c b/bfd/elf32-metag.c
index 4ec2266..f4b1e12 100644
--- a/bfd/elf32-metag.c
+++ b/bfd/elf32-metag.c
@@ -2470,7 +2470,7 @@ elf_metag_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_metag_link_hash_table *htab;
struct elf_metag_link_hash_entry *hh;
struct elf_metag_dyn_reloc_entry *hdh_p;
- asection *s;
+ asection *s, *srel;
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later,
@@ -2564,14 +2564,22 @@ elf_metag_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->etab.sdynrelro;
+ srel = htab->etab.sreldynrelro;
+ }
+ else
+ {
+ s = htab->etab.sdynbss;
+ srel = htab->etab.srelbss;
+ }
if ((eh->root.u.def.section->flags & SEC_ALLOC) != 0 && eh->size != 0)
{
- htab->etab.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
eh->needs_copy = 1;
}
- s = htab->etab.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, eh, s);
}
@@ -2933,7 +2941,8 @@ elf_metag_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (s == htab->etab.splt
|| s == htab->etab.sgot
|| s == htab->etab.sgotplt
- || s == htab->etab.sdynbss)
+ || s == htab->etab.sdynbss
+ || s == htab->etab.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -3215,13 +3224,15 @@ elf_metag_finish_dynamic_symbol (bfd *output_bfd,
|| eh->root.type == bfd_link_hash_defweak)))
abort ();
- s = htab->etab.srelbss;
-
rel.r_offset = (eh->root.u.def.value
+ eh->root.u.def.section->output_offset
+ eh->root.u.def.section->output_section->vma);
rel.r_addend = 0;
rel.r_info = ELF32_R_INFO (eh->dynindx, R_METAG_COPY);
+ if ((eh->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->etab.sreldynrelro;
+ else
+ s = htab->etab.srelbss;
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
}
@@ -4286,6 +4297,7 @@ elf_metag_plt_sym_val (bfd_vma i, const asection *plt,
#define elf_backend_want_plt_sym 0
#define elf_backend_plt_readonly 1
#define elf_backend_dtrel_excludes_plt 1
+#define elf_backend_want_dynrelro 1
#define bfd_elf32_bfd_reloc_type_lookup metag_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup metag_reloc_name_lookup
diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
index 33c6026..31527d5 100644
--- a/bfd/elf32-microblaze.c
+++ b/bfd/elf32-microblaze.c
@@ -2557,9 +2557,8 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf32_mb_link_hash_table *htab;
struct elf32_mb_link_hash_entry * eh;
struct elf32_mb_dyn_relocs *p;
- asection *sdynbss, *s;
+ asection *s, *srel;
unsigned int power_of_two;
- bfd *dynobj;
htab = elf32_mb_hash_table (info);
if (htab == NULL)
@@ -2658,11 +2657,19 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
- dynobj = elf_hash_table (info)->dynobj;
- BFD_ASSERT (dynobj != NULL);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
@@ -2672,21 +2679,20 @@ microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
if (power_of_two > 3)
power_of_two = 3;
- sdynbss = htab->elf.sdynbss;
/* Apply the required alignment. */
- sdynbss->size = BFD_ALIGN (sdynbss->size, (bfd_size_type) (1 << power_of_two));
- if (power_of_two > bfd_get_section_alignment (dynobj, sdynbss))
+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
+ if (power_of_two > s->alignment_power)
{
- if (! bfd_set_section_alignment (dynobj, sdynbss, power_of_two))
+ if (!bfd_set_section_alignment (s->owner, s, power_of_two))
return FALSE;
}
/* Define the symbol as being at this point in the section. */
- h->root.u.def.section = sdynbss;
- h->root.u.def.value = sdynbss->size;
+ h->root.u.def.section = s;
+ h->root.u.def.value = s->size;
/* Increment the section size to make room for the symbol. */
- sdynbss->size += h->size;
+ s->size += h->size;
return TRUE;
}
@@ -3050,7 +3056,9 @@ microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
}
else if (s != htab->elf.splt
&& s != htab->elf.sgot
- && s != htab->elf.sgotplt)
+ && s != htab->elf.sgotplt
+ && s != htab->elf.sdynbss
+ && s != htab->elf.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -3256,14 +3264,15 @@ microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
BFD_ASSERT (h->dynindx != -1);
- s = bfd_get_linker_section (htab->elf.dynobj, ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -3439,6 +3448,7 @@ microblaze_elf_add_symbol_hook (bfd *abfd,
#define elf_backend_want_got_plt 1
#define elf_backend_plt_readonly 1
#define elf_backend_got_header_size 12
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_dtrel_excludes_plt 1
diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c
index d398810..f7649eb 100644
--- a/bfd/elf32-mips.c
+++ b/bfd/elf32-mips.c
@@ -2482,6 +2482,7 @@ static const struct ecoff_debug_swap mips_elf32_ecoff_debug_swap = {
#define elf_backend_ecoff_debug_swap &mips_elf32_ecoff_debug_swap
#define elf_backend_got_header_size (4 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 1
#define elf_backend_may_use_rela_p 0
#define elf_backend_default_use_rela_p 0
diff --git a/bfd/elf32-nios2.c b/bfd/elf32-nios2.c
index a4ce99c..541eb6f 100644
--- a/bfd/elf32-nios2.c
+++ b/bfd/elf32-nios2.c
@@ -5275,14 +5275,16 @@ nios2_elf32_finish_dynamic_symbol (bfd *output_bfd,
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));
- s = htab->root.srelbss;
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_NIOS2_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
+ BFD_ASSERT (s != NULL);
loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -5441,7 +5443,7 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info,
{
struct elf32_nios2_link_hash_table *htab;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;
unsigned align2;
htab = elf32_nios2_hash_table (info);
@@ -5523,19 +5525,22 @@ nios2_elf32_adjust_dynamic_symbol (struct bfd_link_info *info,
determine the address it must put in the global offset table, so
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- s = htab->root.sdynbss;
- BFD_ASSERT (s != NULL);
-
/* We must generate a R_NIOS2_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
{
- asection *srel;
-
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
srel = htab->root.srelbss;
- BFD_ASSERT (srel != NULL);
+ }
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
+ {
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
@@ -5975,7 +5980,7 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
of the dynobj section names depend upon the input files. */
name = bfd_get_section_name (dynobj, s);
- if (strcmp (name, ".plt") == 0)
+ if (s == htab->root.splt)
{
/* Remember whether there is a PLT. */
plt = s->size != 0;
@@ -5998,9 +6003,14 @@ nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
s->reloc_count = 0;
}
}
- else if (CONST_STRNEQ (name, ".got"))
- got = s->size != 0;
- else if (strcmp (name, ".dynbss") != 0)
+ else if (s == htab->root.sgot
+ || s == htab->root.sgotplt)
+ {
+ if (s->size != 0)
+ got = TRUE;
+ }
+ else if (s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -6249,6 +6259,7 @@ const struct bfd_elf_special_section elf32_nios2_special_sections[] =
#define elf_backend_can_refcount 1
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_dtrel_excludes_plt 1
diff --git a/bfd/elf32-or1k.c b/bfd/elf32-or1k.c
index c75a2ce..7fc6b81 100644
--- a/bfd/elf32-or1k.c
+++ b/bfd/elf32-or1k.c
@@ -1944,17 +1944,16 @@ or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak));
- s = bfd_get_section_by_name (h->root.u.def.section->owner,
- ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_OR1K_COPY);
rela.r_addend = 0;
- loc = s->contents;
- loc += s->reloc_count * sizeof (Elf32_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
+ loc = s->contents + s->reloc_count * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
++s->reloc_count;
}
@@ -1995,7 +1994,7 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_or1k_link_hash_entry *eh;
struct elf_or1k_dyn_relocs *p;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;
dynobj = elf_hash_table (info)->dynobj;
@@ -2098,19 +2097,22 @@ or1k_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
if (htab == NULL)
return FALSE;
- s = htab->root.sdynbss;
- BFD_ASSERT (s != NULL);
-
/* We must generate a R_OR1K_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
- if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
{
- asection *srel;
-
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
srel = htab->root.srelbss;
- BFD_ASSERT (srel != NULL);
+ }
+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
+ {
srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
@@ -2472,7 +2474,8 @@ or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (s == htab->root.splt
|| s == htab->root.sgot
|| s == htab->root.sgotplt
- || s == htab->root.sdynbss)
+ || s == htab->root.sdynbss
+ || s == htab->root.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -2742,6 +2745,7 @@ elf32_or1k_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
#define elf_backend_dtrel_excludes_plt 1
+#define elf_backend_want_dynrelro 1
#define bfd_elf32_bfd_link_hash_table_create or1k_elf_link_hash_table_create
#define elf_backend_copy_indirect_symbol or1k_elf_copy_indirect_symbol
diff --git a/bfd/elf32-ppc.c b/bfd/elf32-ppc.c
index 7f541d1..e65ff61 100644
--- a/bfd/elf32-ppc.c
+++ b/bfd/elf32-ppc.c
@@ -5806,6 +5806,8 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->dynsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sdynrelro;
else
s = htab->elf.sdynbss;
BFD_ASSERT (s != NULL);
@@ -5820,6 +5822,8 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
if (ppc_elf_hash_entry (h)->has_sda_refs)
srel = htab->relsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->elf.sreldynrelro;
else
srel = htab->elf.srelbss;
BFD_ASSERT (srel != NULL);
@@ -6636,6 +6640,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|| s == htab->elf.sgotplt
|| s == htab->sbss
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->dynsbss)
{
/* Strip these too. */
@@ -10356,6 +10361,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
if (ppc_elf_hash_entry (h)->has_sda_refs)
s = htab->relsbss;
+ else if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
else
s = htab->elf.srelbss;
BFD_ASSERT (s != NULL);
@@ -10893,6 +10900,7 @@ ppc_elf_finish_dynamic_sections (bfd *output_bfd,
#endif
#define elf_backend_plt_not_loaded 1
+#define elf_backend_want_dynrelro 1
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_rela_normal 1
diff --git a/bfd/elf32-s390.c b/bfd/elf32-s390.c
index 79c4050..b52144a 100644
--- a/bfd/elf32-s390.c
+++ b/bfd/elf32-s390.c
@@ -1607,7 +1607,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_s390_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
/* STT_GNU_IFUNC symbol must go through PLT. */
if (s390_is_ifunc_symbol_p (h))
@@ -1757,14 +1757,22 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_390_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -2157,6 +2165,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->irelifunc)
@@ -3800,6 +3809,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
bfd_byte *loc;
/* This symbols needs a copy reloc. Set it up. */
@@ -3807,7 +3817,8 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();
rela.r_offset = (h->root.u.def.value
@@ -3815,8 +3826,11 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_390_COPY);
rela.r_addend = 0;
- loc = htab->elf.srelbss->contents;
- loc += htab->elf.srelbss->reloc_count++ * sizeof (Elf32_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -4154,6 +4168,7 @@ elf32_s390_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
#define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_info_to_howto elf_s390_info_to_howto
diff --git a/bfd/elf32-sparc.c b/bfd/elf32-sparc.c
index 528cba2..8610945 100644
--- a/bfd/elf32-sparc.c
+++ b/bfd/elf32-sparc.c
@@ -245,6 +245,7 @@ elf32_sparc_add_symbol_hook (bfd * abfd,
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 4
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_add_symbol_hook elf32_sparc_add_symbol_hook
diff --git a/bfd/elf32-tic6x.c b/bfd/elf32-tic6x.c
index c2b22ee..1ccbf9c 100644
--- a/bfd/elf32-tic6x.c
+++ b/bfd/elf32-tic6x.c
@@ -1860,13 +1860,15 @@ elf32_tic6x_finish_dynamic_symbol (bfd * output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *s;
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();
rel.r_offset = (h->root.u.def.value
@@ -1874,8 +1876,12 @@ elf32_tic6x_finish_dynamic_symbol (bfd * output_bfd,
+ h->root.u.def.section->output_offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_C6000_COPY);
rel.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
- elf32_tic6x_install_rela (output_bfd, htab->elf.srelbss, &rel);
+ elf32_tic6x_install_rela (output_bfd, s, &rel);
}
/* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */
@@ -2061,7 +2067,7 @@ elf32_tic6x_adjust_dynamic_symbol (struct bfd_link_info *info,
{
struct elf32_tic6x_link_hash_table *htab;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;
dynobj = elf_hash_table (info)->dynobj;
@@ -2146,14 +2152,22 @@ elf32_tic6x_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_C6000_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
h->needs_copy = 1;
}
- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -3376,7 +3390,8 @@ elf32_tic6x_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
else if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -4369,6 +4384,7 @@ elf32_tic6x_write_section (bfd *output_bfd,
#define elf_backend_can_refcount 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_dynbss 1
+#define elf_backend_want_dynrelro 1
#define elf_backend_plt_readonly 1
#define elf_backend_rela_normal 1
#define elf_backend_got_header_size 8
diff --git a/bfd/elf32-tilegx.c b/bfd/elf32-tilegx.c
index bf1ad6b..1b4aa8f 100644
--- a/bfd/elf32-tilegx.c
+++ b/bfd/elf32-tilegx.c
@@ -128,6 +128,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
#define elf_backend_plt_alignment 6
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 4
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0
diff --git a/bfd/elf32-tilepro.c b/bfd/elf32-tilepro.c
index 18aabb0..f95cd27 100644
--- a/bfd/elf32-tilepro.c
+++ b/bfd/elf32-tilepro.c
@@ -2062,7 +2062,7 @@ tilepro_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct tilepro_elf_link_hash_table *htab;
struct tilepro_elf_link_hash_entry * eh;
struct tilepro_elf_dyn_relocs *p;
- asection *s;
+ asection *s, *srel;
htab = tilepro_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -2164,13 +2164,23 @@ tilepro_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += TILEPRO_ELF_RELA_BYTES;
+ srel->size += TILEPRO_ELF_RELA_BYTES;
h->needs_copy = 1;
}
- return _bfd_elf_adjust_dynamic_copy (info, h, htab->elf.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* Allocate space in .plt, .got and associated reloc sections for
@@ -2565,7 +2575,8 @@ tilepro_elf_size_dynamic_sections (bfd *output_bfd,
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -3797,14 +3808,15 @@ tilepro_elf_finish_dynamic_symbol (bfd *output_bfd,
/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);
- s = htab->elf.srelbss;
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = ELF32_R_INFO (h->dynindx, R_TILEPRO_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
tilepro_elf_append_rela_32 (output_bfd, s, &rela);
}
@@ -4045,6 +4057,7 @@ tilepro_additional_program_headers (bfd *abfd,
#define elf_backend_plt_alignment 6
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size GOT_ENTRY_SIZE
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0
diff --git a/bfd/elf64-mips.c b/bfd/elf64-mips.c
index 8cd0a73..1a39522 100644
--- a/bfd/elf64-mips.c
+++ b/bfd/elf64-mips.c
@@ -4467,6 +4467,7 @@ const struct elf_size_info mips_elf64_size_info =
#define elf_backend_grok_psinfo elf64_mips_grok_psinfo
#define elf_backend_got_header_size (8 * MIPS_RESERVED_GOTNO)
+#define elf_backend_want_dynrelro 1
/* MIPS ELF64 can use a mixture of REL and RELA, but some Relocations
work better/work only in RELA, so we default to this. */
diff --git a/bfd/elf64-ppc.c b/bfd/elf64-ppc.c
index c421426..9520777 100644
--- a/bfd/elf64-ppc.c
+++ b/bfd/elf64-ppc.c
@@ -72,6 +72,7 @@ static bfd_vma opd_entry_value
#define elf_backend_plt_alignment 3
#define elf_backend_plt_not_loaded 1
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_rela_normal 1
@@ -7235,7 +7236,7 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct ppc_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
htab = ppc_hash_table (info);
if (htab == NULL)
@@ -7365,14 +7366,22 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rela.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf64_External_Rela);
+ srel->size += sizeof (Elf64_External_Rela);
h->needs_copy = 1;
}
- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -10174,7 +10183,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|| s == htab->elf.splt
|| s == htab->elf.iplt
|| s == htab->glink
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -10227,7 +10237,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
but this way if it does we get a R_PPC64_NONE reloc in .rela
sections instead of garbage.
We also rely on the section contents being zero when writing
- the GOT. */
+ the GOT and .dynrelro. */
s->contents = bfd_zalloc (dynobj, s->size);
if (s->contents == NULL)
return FALSE;
@@ -15421,11 +15431,13 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
/* This symbol needs a copy reloc. Set it up. */
+ asection *srel;
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();
rela.r_offset = (h->root.u.def.value
@@ -15433,8 +15445,12 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.section->output_offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_COPY);
rela.r_addend = 0;
- loc = htab->elf.srelbss->contents;
- loc += htab->elf.srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->elf.sreldynrelro;
+ else
+ srel = htab->elf.srelbss;
+ loc = srel->contents;
+ loc += srel->reloc_count++ * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}
diff --git a/bfd/elf64-s390.c b/bfd/elf64-s390.c
index ab2bbaa..64a74c5 100644
--- a/bfd/elf64-s390.c
+++ b/bfd/elf64-s390.c
@@ -1541,7 +1541,7 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_s390_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
/* STT_GNU_IFUNC symbol must go through PLT. */
if (s390_is_ifunc_symbol_p (h))
@@ -1693,14 +1693,22 @@ elf_s390_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_390_COPY reloc to tell the dynamic linker to
copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (Elf64_External_Rela);
+ srel->size += sizeof (Elf64_External_Rela);
h->needs_copy = 1;
}
- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -2099,6 +2107,7 @@ elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->elf.iplt
|| s == htab->elf.igotplt
|| s == htab->irelifunc)
@@ -3585,6 +3594,7 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
bfd_byte *loc;
/* This symbols needs a copy reloc. Set it up. */
@@ -3600,8 +3610,11 @@ elf_s390_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.section->output_offset);
rela.r_info = ELF64_R_INFO (h->dynindx, R_390_COPY);
rela.r_addend = 0;
- loc = htab->elf.srelbss->contents;
- loc += htab->elf.srelbss->reloc_count++ * sizeof (Elf64_External_Rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ loc = s->contents + s->reloc_count++ * sizeof (Elf64_External_Rela);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -3979,6 +3992,7 @@ const struct elf_size_info s390_elf64_size_info =
#define elf_backend_plt_readonly 1
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 24
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_info_to_howto elf_s390_info_to_howto
diff --git a/bfd/elf64-sparc.c b/bfd/elf64-sparc.c
index 65fb5e4..eecccd1 100644
--- a/bfd/elf64-sparc.c
+++ b/bfd/elf64-sparc.c
@@ -920,6 +920,7 @@ const struct elf_size_info elf64_sparc_size_info =
#define elf_backend_plt_readonly 0
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
/* Section 5.2.4 of the ABI specifies a 256-byte boundary for the table. */
diff --git a/bfd/elf64-tilegx.c b/bfd/elf64-tilegx.c
index c281474..f3f9076 100644
--- a/bfd/elf64-tilegx.c
+++ b/bfd/elf64-tilegx.c
@@ -129,6 +129,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
#define elf_backend_plt_alignment 6
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size 8
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index d5a36bc..5b3dd8a 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -2828,7 +2828,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_x86_64_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
struct elf_x86_64_link_hash_entry *eh;
struct elf_dyn_relocs *p;
@@ -2986,16 +2986,24 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_X86_64_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
const struct elf_backend_data *bed;
bed = get_elf_backend_data (info->output_bfd);
- htab->elf.srelbss->size += bed->s->sizeof_rela;
+ srel->size += bed->s->sizeof_rela;
h->needs_copy = 1;
}
- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -3811,7 +3819,8 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
|| s == htab->plt_bnd
|| s == htab->plt_got
|| s == htab->plt_eh_frame
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
/* This symbol needs a copy reloc. Set it up. */
if (h->dynindx == -1
|| (h->root.type != bfd_link_hash_defined
&& h->root.type != bfd_link_hash_defweak)
- || htab->elf.srelbss == NULL)
+ || htab->elf.srelbss == NULL
+ || htab->elf.sreldynrelro == NULL)
abort ();
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_offset);
rela.r_info = htab->r_info (h->dynindx, R_X86_64_COPY);
rela.r_addend = 0;
- elf_append_rela (output_bfd, htab->elf.srelbss, &rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ elf_append_rela (output_bfd, s, &rela);
}
return TRUE;
@@ -6719,6 +6734,7 @@ static const struct bfd_elf_special_section
#define elf_backend_extern_protected_data 1
#define elf_backend_caches_rawsize 1
#define elf_backend_dtrel_excludes_plt 1
+#define elf_backend_want_dynrelro 1
#define elf_info_to_howto elf_x86_64_info_to_howto
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9728e29..d8d40f1 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -429,6 +429,19 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
return FALSE;
htab->sdynbss = s;
+ if (bed->want_dynrelro)
+ {
+ /* Similarly, but for symbols that were originally in read-only
+ sections. */
+ s = bfd_make_section_anyway_with_flags (abfd, ".data.rel.ro",
+ (SEC_ALLOC | SEC_READONLY
+ | SEC_HAS_CONTENTS
+ | SEC_LINKER_CREATED));
+ if (s == NULL)
+ return FALSE;
+ htab->sdynrelro = s;
+ }
+
/* The .rel[a].bss section holds copy relocs. This section is not
normally needed. We need to create it here, though, so that the
linker will map it to an output section. We can't just create it
@@ -450,6 +463,19 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info)
|| ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align))
return FALSE;
htab->srelbss = s;
+
+ if (bed->want_dynrelro)
+ {
+ s = (bfd_make_section_anyway_with_flags
+ (abfd, (bed->rela_plts_and_copies_p
+ ? ".rela.data.rel.ro" : ".rel.data.rel.ro"),
+ flags | SEC_READONLY));
+ if (s == NULL
+ || ! bfd_set_section_alignment (abfd, s,
+ bed->s->log_file_align))
+ return FALSE;
+ htab->sreldynrelro = s;
+ }
}
}
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 8a55596..0103b01 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -6833,7 +6833,7 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
struct elf_aarch64_link_hash_table *htab;
- asection *s;
+ asection *s, *srel;
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later,
@@ -6910,14 +6910,22 @@ elfNN_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
/* We must generate a R_AARCH64_COPY reloc to tell the dynamic linker
to copy the initial value out of the dynamic object and into the
runtime process image. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
+ srel = htab->root.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->root.srelbss->size += RELOC_SIZE (htab);
+ srel->size += RELOC_SIZE (htab);
h->needs_copy = 1;
}
- s = htab->root.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -8517,7 +8525,8 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|| s == htab->root.sgotplt
|| s == htab->root.iplt
|| s == htab->root.igotplt
- || s == htab->root.sdynbss)
+ || s == htab->root.sdynbss
+ || s == htab->root.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
bfd_byte *loc;
/* This symbol needs a copy reloc. Set it up. */
+ h->root.u.def.section->output_offset);
rela.r_info = ELFNN_R_INFO (h->dynindx, AARCH64_R (COPY));
rela.r_addend = 0;
- loc = htab->root.srelbss->contents;
- loc += htab->root.srelbss->reloc_count++ * RELOC_SIZE (htab);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->root.sreldynrelro;
+ else
+ s = htab->root.srelbss;
+ loc = s->contents + s->reloc_count++ * RELOC_SIZE (htab);
bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc);
}
@@ -9390,6 +9403,7 @@ const struct elf_size_info elfNN_aarch64_size_info =
#define elf_backend_plt_readonly 1
#define elf_backend_want_got_plt 1
#define elf_backend_want_plt_sym 0
+#define elf_backend_want_dynrelro 1
#define elf_backend_may_use_rel_p 0
#define elf_backend_may_use_rela_p 1
#define elf_backend_default_use_rela_p 1
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index db4b782..69907bd 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -862,7 +862,7 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct riscv_elf_link_hash_entry * eh;
struct riscv_elf_dyn_relocs *p;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;
htab = riscv_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -965,16 +965,26 @@ riscv_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += sizeof (ElfNN_External_Rela);
+ srel->size += sizeof (ElfNN_External_Rela);
h->needs_copy = 1;
}
if (eh->tls_type & ~GOT_NORMAL)
return _bfd_elf_adjust_dynamic_copy (info, h, htab->sdyntdata);
- return _bfd_elf_adjust_dynamic_copy (info, h, htab->elf.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* Allocate space in .plt, .got and associated reloc sections for
@@ -1328,7 +1338,8 @@ riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -2389,6 +2400,7 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rela;
+ asection *s;
/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);
@@ -2396,7 +2408,11 @@ riscv_elf_finish_dynamic_symbol (bfd *output_bfd,
rela.r_offset = sec_addr (h->root.u.def.section) + h->root.u.def.value;
rela.r_info = ELFNN_R_INFO (h->dynindx, R_RISCV_COPY);
rela.r_addend = 0;
- riscv_elf_append_rela (output_bfd, htab->elf.srelbss, &rela);
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
+ riscv_elf_append_rela (output_bfd, s, &rela);
}
/* Mark some specially defined symbols as absolute. */
@@ -3213,6 +3229,7 @@ riscv_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
#define elf_backend_plt_alignment 4
#define elf_backend_want_plt_sym 1
#define elf_backend_got_header_size (ARCH_SIZE / 8)
+#define elf_backend_want_dynrelro 1
#define elf_backend_rela_normal 1
#define elf_backend_default_execstack 0
diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c
index 086d537..7c7cd38 100644
--- a/bfd/elfxx-mips.c
+++ b/bfd/elfxx-mips.c
@@ -9129,6 +9129,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
bfd *dynobj;
struct mips_elf_link_hash_entry *hmips;
struct mips_elf_link_hash_table *htab;
+ asection *s, *srel;
htab = mips_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -9371,10 +9372,20 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->root.sdynrelro;
+ srel = htab->root.sreldynrelro;
+ }
+ else
+ {
+ s = htab->root.sdynbss;
+ srel = htab->root.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
{
if (htab->is_vxworks)
- htab->root.srelbss->size += sizeof (Elf32_External_Rela);
+ srel->size += sizeof (Elf32_External_Rela);
else
mips_elf_allocate_dynamic_relocations (dynobj, info, 1);
h->needs_copy = 1;
@@ -9384,7 +9395,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
dynamic will now refer to the local copy instead. */
hmips->possibly_dynamic_relocs = 0;
- return _bfd_elf_adjust_dynamic_copy (info, h, htab->root.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* This function is called after all the input files have been read,
@@ -9906,7 +9917,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
&& s != htab->root.sgot
&& s != htab->root.sgotplt
&& s != htab->sstubs
- && s != htab->root.sdynbss)
+ && s != htab->root.sdynbss
+ && s != htab->root.sdynrelro)
{
/* It's not one of our sections, so don't allocate space. */
continue;
@@ -11296,6 +11308,8 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
if (h->needs_copy)
{
Elf_Internal_Rela rel;
+ asection *srel;
+ bfd_byte *loc;
BFD_ASSERT (h->dynindx != -1);
@@ -11304,11 +11318,13 @@ _bfd_mips_vxworks_finish_dynamic_symbol (bfd *output_bfd,
+ h->root.u.def.value);
rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_COPY);
rel.r_addend = 0;
- bfd_elf32_swap_reloca_out (output_bfd, &rel,
- htab->root.srelbss->contents
- + (htab->root.srelbss->reloc_count
- * sizeof (Elf32_External_Rela)));
- ++htab->root.srelbss->reloc_count;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ srel = htab->root.sreldynrelro;
+ else
+ srel = htab->root.srelbss;
+ loc = srel->contents + srel->reloc_count * sizeof (Elf32_External_Rela);
+ bfd_elf32_swap_reloca_out (output_bfd, &rel, loc);
+ ++srel->reloc_count;
}
/* If this is a mips16/microMIPS symbol, force the value to be even. */
diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
index 050993c..d7b2688 100644
--- a/bfd/elfxx-sparc.c
+++ b/bfd/elfxx-sparc.c
@@ -2086,7 +2086,7 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct _bfd_sparc_elf_link_hash_table *htab;
struct _bfd_sparc_elf_link_hash_entry * eh;
struct _bfd_sparc_elf_dyn_relocs *p;
- asection *s;
+ asection *s, *srel;
htab = _bfd_sparc_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -2199,14 +2199,22 @@ _bfd_sparc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += SPARC_ELF_RELA_BYTES (htab);
+ srel->size += SPARC_ELF_RELA_BYTES (htab);
h->needs_copy = 1;
}
- s = htab->elf.sdynbss;
-
return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
@@ -2686,6 +2694,7 @@ _bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro
|| s == htab->elf.iplt
|| s == htab->elf.sgotplt)
{
@@ -4527,15 +4536,15 @@ _bfd_sparc_elf_finish_dynamic_symbol (bfd *output_bfd,
/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);
- s = bfd_get_linker_section (h->root.u.def.section->owner,
- ".rela.bss");
- BFD_ASSERT (s != NULL);
-
rela.r_offset = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
rela.r_info = SPARC_ELF_R_INFO (htab, NULL, h->dynindx, R_SPARC_COPY);
rela.r_addend = 0;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
sparc_elf_append_rela (output_bfd, s, &rela);
}
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index aff8621..7f08128 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -108,6 +108,9 @@
#ifndef elf_backend_want_dynbss
#define elf_backend_want_dynbss 1
#endif
+#ifndef elf_backend_want_dynrelro
+#define elf_backend_want_dynrelro 0
+#endif
#ifndef elf_backend_want_p_paddr_set_to_zero
#define elf_backend_want_p_paddr_set_to_zero 0
#endif
@@ -855,6 +858,7 @@ static struct elf_backend_data elfNN_bed =
elf_backend_can_refcount,
elf_backend_want_got_sym,
elf_backend_want_dynbss,
+ elf_backend_want_dynrelro,
elf_backend_want_p_paddr_set_to_zero,
elf_backend_default_execstack,
elf_backend_caches_rawsize,
diff --git a/bfd/elfxx-tilegx.c b/bfd/elfxx-tilegx.c
index 92b9de8..ce4fb07 100644
--- a/bfd/elfxx-tilegx.c
+++ b/bfd/elfxx-tilegx.c
@@ -2327,7 +2327,7 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
struct tilegx_elf_link_hash_entry * eh;
struct tilegx_elf_dyn_relocs *p;
bfd *dynobj;
- asection *s;
+ asection *s, *srel;
htab = tilegx_elf_hash_table (info);
BFD_ASSERT (htab != NULL);
@@ -2431,13 +2431,23 @@ tilegx_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
to copy the initial value out of the dynamic object and into the
runtime process image. We need to remember the offset into the
.rel.bss section we are going to use. */
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ {
+ s = htab->elf.sdynrelro;
+ srel = htab->elf.sreldynrelro;
+ }
+ else
+ {
+ s = htab->elf.sdynbss;
+ srel = htab->elf.srelbss;
+ }
if ((h->root.u.def.section->flags & SEC_ALLOC) != 0 && h->size != 0)
{
- htab->elf.srelbss->size += TILEGX_ELF_RELA_BYTES (htab);
+ srel->size += TILEGX_ELF_RELA_BYTES (htab);
h->needs_copy = 1;
}
- return _bfd_elf_adjust_dynamic_copy (info, h, htab->elf.sdynbss);
+ return _bfd_elf_adjust_dynamic_copy (info, h, s);
}
/* Allocate space in .plt, .got and associated reloc sections for
@@ -2826,7 +2836,8 @@ tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
if (s == htab->elf.splt
|| s == htab->elf.sgot
|| s == htab->elf.sgotplt
- || s == htab->elf.sdynbss)
+ || s == htab->elf.sdynbss
+ || s == htab->elf.sdynrelro)
{
/* Strip this section if we don't need it; see the
comment below. */
@@ -4187,7 +4198,10 @@ tilegx_elf_finish_dynamic_symbol (bfd *output_bfd,
/* This symbols needs a copy reloc. Set it up. */
BFD_ASSERT (h->dynindx != -1);
- s = htab->elf.srelbss;
+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
+ s = htab->elf.sreldynrelro;
+ else
+ s = htab->elf.srelbss;
BFD_ASSERT (s != NULL);
rela.r_offset = (h->root.u.def.value
diff --git a/ld/testsuite/ld-arm/farcall-mixed-app-v5.d b/ld/testsuite/ld-arm/farcall-mixed-app-v5.d
index b570bad..af44198 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-app-v5.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-app-v5.d
.*: e1a0c00d mov ip, sp
.*: e92dd800 push {fp, ip, lr, pc}
- .*: eb0000.. bl .* <__lib_func1_veneer>
- .*: eb0000.. bl .* <__lib_func2_veneer>
+ .*: eb00000(6|8) bl .* <__lib_func1_veneer>
+ .*: eb00000(7|5) bl .* <__lib_func2_veneer>
.*: e89d6800 ldm sp, {fp, sp, lr}
.*: e12fff1e bx lr
.*: e1a00000 nop ; \(mov r0, r0\)
.*: e12fff1e bx lr
#...
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func1_veneer\+0x4>
- .*: 000081e8 .word 0x000081e8
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func2_veneer\+0x4>
- .*: 000081dc .word 0x000081dc
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(1|2)_veneer\+0x4>
+ .*: 000081(e8|dc) .word 0x000081(e8|dc)
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(2|1)_veneer\+0x4>
+ .*: 000081(dc|e8) .word 0x000081(dc|e8)
diff --git a/ld/testsuite/ld-arm/farcall-mixed-app.d b/ld/testsuite/ld-arm/farcall-mixed-app.d
index 9fa97dc..f3be54f 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-app.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-app.d
.*: e1a0c00d mov ip, sp
.*: e92dd800 push {fp, ip, lr, pc}
- .*: eb000006 bl .* <__lib_func1_veneer>
- .*: eb000007 bl .* <__lib_func2_veneer>
+ .*: eb00000(6|8) bl .* <__lib_func1_veneer>
+ .*: eb00000(7|5) bl .* <__lib_func2_veneer>
.*: e89d6800 ldm sp, {fp, sp, lr}
.*: e12fff1e bx lr
.*: e1a00000 nop ; \(mov r0, r0\)
.*: e12fff1e bx lr
#...
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func1_veneer\+0x4>
- .*: 000081ec .word 0x000081ec
- .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func2_veneer\+0x4>
- .*: 000081e0 .word 0x000081e0
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(1|2)_veneer\+0x4>
+ .*: 000081e(c|0) .word 0x000081e(c|0)
+ .*: e51ff004 ldr pc, \[pc, #-4\] ; .* <__lib_func(2|1)_veneer\+0x4>
+ .*: 000081e(0|c) .word 0x000081e(0|c)
diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d b/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d
index fa52ad1..83b15a0 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-lib-v4t.d
...
- .*: f000 f80e bl 2000390 <__app_func_from_thumb>
- .*: f000 f804 bl 2000380 <__app_func_weak_from_thumb>
+ .*: f000 f80(e|6) bl .* <__app_func_from_thumb>
+ .*: f000 f80(4|c) bl .* <__app_func_weak_from_thumb>
.*: 4770 bx lr
#...
.*: 4778 bx pc
.*: 46c0 nop ; \(mov r8, r8\)
- .*: e59fc000 ldr ip, \[pc\] ; 200038c <__app_func_weak_from_thumb\+0xc>
+ .*: e59fc000 ldr ip, \[pc\] ; 200038c <__app_func(_weak)?_from_thumb\+0xc>
.*: e08cf00f add pc, ip, pc
- .*: fdffff28 .word 0xfdffff28
+ .*: fdffff(2|1)8 .word 0xfdffff(2|1)8
.*: 4778 bx pc
.*: 46c0 nop ; \(mov r8, r8\)
- .*: e59fc000 ldr ip, \[pc\] ; 200039c <__app_func_from_thumb\+0xc>
+ .*: e59fc000 ldr ip, \[pc\] ; 200039c <__app_func(_weak)?_from_thumb\+0xc>
.*: e08cf00f add pc, ip, pc
- .*: fdffff08 .word 0xfdffff08
+ .*: fdffff(0|1)8 .word 0xfdffff(0|1)8
.*: e59fc004 ldr ip, \[pc, #4\] ; 20003ac <lib_func3\+0xc>
diff --git a/ld/testsuite/ld-arm/farcall-mixed-lib.d b/ld/testsuite/ld-arm/farcall-mixed-lib.d
index ad7352b..d256477 100644
--- a/ld/testsuite/ld-arm/farcall-mixed-lib.d
+++ b/ld/testsuite/ld-arm/farcall-mixed-lib.d
...
- .*: f000 e80c blx 200037c <__app_func_from_thumb>
- .*: f000 e804 blx 2000370 <__app_func_weak_from_thumb>
+ .*: f000 e80(c|6) blx .* <__app_func_from_thumb>
+ .*: f000 e80(4|a) blx .* <__app_func_weak_from_thumb>
.*: 4770 bx lr
#...
- .*: e59fc000 ldr ip, \[pc\] ; 2000378 <__app_func_weak_from_thumb\+0x8>
+ .*: e59fc000 ldr ip, \[pc\] ; 2000378 <__app_func(_weak)?_from_thumb\+0x8>
.*: e08ff00c add pc, pc, ip
- .*: fdffff34 .word 0xfdffff34
+ .*: fdffff(34|28) .word 0xfdffff(34|28)
- .*: e59fc000 ldr ip, \[pc\] ; 2000384 <__app_func_from_thumb\+0x8>
+ .*: e59fc000 ldr ip, \[pc\] ; 2000384 <__app_func(_weak)?_from_thumb\+0x8>
.*: e08ff00c add pc, pc, ip
- .*: fdffff1c .word 0xfdffff1c
+ .*: fdffff(1c|28) .word 0xfdffff(1c|28)
...
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index f93ad46..9b1fbeb 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -127,6 +127,20 @@ if { [check_shared_lib_support] } then {
{symbolic-func.s} {{readelf {-r --wide} symbolic-func.r}}
"symbolic-func.so"}
}
+ # xfail on tic6x due to non-PIC/non-PID warnings
+ setup_xfail "tic6x-*-*"
+ run_ld_link_tests {
+ {"Build pr20995.so"
+ "-shared" "" ""
+ {pr20995b.s} {} "pr20995.so"}
+ }
+ # These targets don't copy dynamic variables into .bss.
+ setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*"
+ run_ld_link_tests {
+ {"pr20995"
+ "" "tmpdir/pr20995.so" ""
+ {pr20995a.s} {{readelf {-S --wide} pr20995.r}} "pr20995"}
+ }
}
set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
diff --git a/ld/testsuite/ld-elf/pr20995.r b/ld/testsuite/ld-elf/pr20995.r
new file mode 100644
index 0000000..7336de6
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr20995.r
@@ -0,0 +1,5 @@
+#...
+.* \.data\.rel\.ro +PROGBITS +[^ ]+ [^ ]+ [^ ]*[1-9a-f]0* .*
+#...
+.* \.bss +NOBITS +[^ ]+ [^ ]+ [^ ]*[1-9a-f]0* .*
+#...
diff --git a/ld/testsuite/ld-elf/pr20995a.s b/ld/testsuite/ld-elf/pr20995a.s
new file mode 100644
index 0000000..8da589c
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr20995a.s
@@ -0,0 +1,11 @@
+ .text
+ .global start
+ .global _start
+ .global __start
+ .global main
+ .dc.a rw
+ .dc.a ro
diff --git a/ld/testsuite/ld-elf/pr20995b.s b/ld/testsuite/ld-elf/pr20995b.s
new file mode 100644
index 0000000..7ff76ee
--- /dev/null
+++ b/ld/testsuite/ld-elf/pr20995b.s
@@ -0,0 +1,13 @@
+ .data
+ .type rw,%object
+ .globl rw
+ .dc.a 0
+ .size rw, . - rw
+
+ .text
+ .type ro,%object
+ .globl ro
+ .dc.a 0
+ .size ro, . - ro
--
Alan Modra
Australia Development Lab, IBM
Alan Modra
2017-01-03 11:56:48 UTC
Permalink
Post by Christophe Lyon
FAIL: Build pr20995-2.so
FAIL: pr20995-2
for arm-netbsdelf and arm-none-eabi
That will be because these tests require working -z relro support, at
least to the point of generating a GNU_RELRO header.
--
Alan Modra
Australia Development Lab, IBM
Kyrill Tkachov
2017-01-06 10:47:03 UTC
Permalink
Post by Alan Modra
Post by Christophe Lyon
FAIL: Build pr20995-2.so
FAIL: pr20995-2
for arm-netbsdelf and arm-none-eabi
That will be because these tests require working -z relro support, at
least to the point of generating a GNU_RELRO header.
So should these tests be XFAILED on arm targets?

Thanks,
Kyrill
Szabolcs Nagy
2017-01-06 18:43:05 UTC
Permalink
Post by Kyrill Tkachov
Post by Alan Modra
Post by Christophe Lyon
FAIL: Build pr20995-2.so
FAIL: pr20995-2
for arm-netbsdelf and arm-none-eabi
That will be because these tests require working -z relro support, at
least to the point of generating a GNU_RELRO header.
So should these tests be XFAILED on arm targets?
i think arm has -z relro support however PT_GNU_RELRO
header is not emitted if there is no DATA_SEGMENT_RELRO_END
specification in the linker script (which we probably
only have on linux, since shared libs and related features
are not used on baremetal targets).

i assume we could change the arm elf linker script, but
i don't know what are the exact implications of that.
Alan Modra
2017-01-06 22:41:20 UTC
Permalink
Post by Szabolcs Nagy
Post by Kyrill Tkachov
Post by Alan Modra
Post by Christophe Lyon
FAIL: Build pr20995-2.so
FAIL: pr20995-2
for arm-netbsdelf and arm-none-eabi
That will be because these tests require working -z relro support, at
least to the point of generating a GNU_RELRO header.
So should these tests be XFAILED on arm targets?
Probably not.
Post by Szabolcs Nagy
i think arm has -z relro support however PT_GNU_RELRO
header is not emitted if there is no DATA_SEGMENT_RELRO_END
specification in the linker script (which we probably
only have on linux, since shared libs and related features
are not used on baremetal targets).
i assume we could change the arm elf linker script, but
i don't know what are the exact implications of that.
COMMONPAGESIZE needs to be defined in a target's ld/emulparams/ file.
-z relro will then actually do something.

Before doing this you probably should check that the target system
ld.so will not be confused by the presense of a PT_GNU_RELRO header.
(I think current netbsd does support it.)

Since arm-none-eabi is a generic target, anyone using it likely
doesn't create shared libraries. However, I see that shared libs are
supported so you may as well support relro there too.
--
Alan Modra
Australia Development Lab, IBM
Jiong Wang
2017-01-26 17:16:01 UTC
Permalink
Post by Alan Modra
Post by Szabolcs Nagy
Post by Kyrill Tkachov
Post by Alan Modra
Post by Christophe Lyon
FAIL: Build pr20995-2.so
FAIL: pr20995-2
for arm-netbsdelf and arm-none-eabi
That will be because these tests require working -z relro support, at
least to the point of generating a GNU_RELRO header.
So should these tests be XFAILED on arm targets?
Probably not.
Post by Szabolcs Nagy
i think arm has -z relro support however PT_GNU_RELRO
header is not emitted if there is no DATA_SEGMENT_RELRO_END
specification in the linker script (which we probably
only have on linux, since shared libs and related features
are not used on baremetal targets).
i assume we could change the arm elf linker script, but
i don't know what are the exact implications of that.
COMMONPAGESIZE needs to be defined in a target's ld/emulparams/ file.
-z relro will then actually do something.
Before doing this you probably should check that the target system
ld.so will not be confused by the presense of a PT_GNU_RELRO header.
(I think current netbsd does support it.)
Since arm-none-eabi is a generic target, anyone using it likely
doesn't create shared libraries. However, I see that shared libs are
supported so you may as well support relro there too.
Thanks for the thoughts.

As discussed on https://sourceware.org/bugzilla/show_bug.cgi?id=20995

For arm*-*-eabi*, I'd be conservative to just XFAIL on it. If one target is
surely doesn't care about disk size, it then can define COMMONPAGESIZE in the
corresponding emulparm file as suggested in this email thread. I can't find
any other harm of defining this constant.

disk size issue
===
If we enable GNU relro support through defining COMMONPAGESIZE in emulparm
then there will be observable impacts on disk size as LD will try to pad text
section sometimes to save one memory page as the pad can avoid the duplicated
mapping of the last page of text segment, this however will cause waste of up to
COMMONPAGESIZE (0x1000 on arm at default) disk size.

for example
===1.s===
.text
.fill 0x4, 1, 0
.data
.fill 0xffd, 1, 0

as -o 1.o 1.s
ld-new.original -o after.exe 1.o -e0
ld-new.after -o before.exe 1.o -e0

disk size before/after 37568/41660, a 4092 bytes increase.

OK for master?

Thanks.

ld/
2017-01-26 Jiong Wang <***@arm.com>

* testsuite/ld-elf/elf.exp ("pr20995-2", "Build pr20995-2.so"): XFAIL on
arm*-*-eabi*.
Alan Modra
2017-01-27 15:10:12 UTC
Permalink
Post by Jiong Wang
disk size issue
===
If we enable GNU relro support through defining COMMONPAGESIZE in emulparm
then there will be observable impacts on disk size as LD will try to pad text
section sometimes to save one memory page as the pad can avoid the duplicated
mapping of the last page of text segment, this however will cause waste of up to
COMMONPAGESIZE (0x1000 on arm at default) disk size.
for example
===1.s===
.text
.fill 0x4, 1, 0
.data
.fill 0xffd, 1, 0
as -o 1.o 1.s
ld-new.original -o after.exe 1.o -e0
ld-new.after -o before.exe 1.o -e0
disk size before/after 37568/41660, a 4092 bytes increase.
I'll note that 32k or so of this is due to the combination of
TEXT_START_ADDR, EMBEDDED and MAXPAGESIZE. So the concern about disk
size vs. relro would be better directed at fixing that, but please
don't ask me how to untangle emulparams/armelf.sh!
--
Alan Modra
Australia Development Lab, IBM
Nick Clifton
2017-01-27 16:00:31 UTC
Permalink
Hi Jiong,
Post by Jiong Wang
OK for master?
Almost...

+ # xfail on arm*-*-eabi*. The list can be enlarged to those targets that
+ # don't support GNU_RELRO.
+ setup_xfail "arm*-*-eabi*"
run_ld_link_tests {
{"Build pr20995-2.so"
"-shared -z relro" "" ""
@@ -154,7 +157,7 @@ if { [check_shared_lib_support] } then {
"pr20995" \
"" "tmpdir/pr20995.so" "$AFLAGS_NONPIC" \
{pr20995a.s} {{readelf {-S --wide} pr20995.r}} "pr20995"]]
- setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*"
+ setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*" "arm*-*-eabi*"
run_ld_link_tests [list \
[list \
"pr20995-2" \

I think that you ought to extend the comment in the first thunk,
and add a comment in the second thunk, pointing readers at this
thread. That way, future readers of this test can find out more
about why the xfails are there.

Approved with this change.

Cheers
Nick

Maciej W. Rozycki
2017-01-18 18:07:58 UTC
Permalink
ld/
PR ld/20995
* testsuite/ld-elf/elf.exp: Set GAS flags correctly for the
`mips*-*-*' target and `pr20995' and `pr20995-2' tests.
---
Post by Alan Modra
am33_2.0-linux +FAIL: pr20995
arc-linux-uclibc +FAIL: pr20995
crisv32-linux +FAIL: pr20995
hppa64-hp-hpux11.23 +FAIL: pr20995
hppa64-linux +FAIL: pr20995
i370-linux +FAIL: Build pr20995.so
i370-linux +FAIL: pr20995
m68k-elf +FAIL: pr20995
m68k-linux +FAIL: pr20995
mips64-linux +FAIL: pr20995
mipsel-linux-gnu +FAIL: pr20995
mipsisa32el-linux +FAIL: pr20995
mips-linux +FAIL: pr20995
mn10300-elf +FAIL: pr20995
riscv32-elf +FAIL: pr20995
riscv64-elf +FAIL: pr20995
score-elf +FAIL: pr20995
sh-linux +FAIL: pr20995
shl-unknown-netbsdelf +FAIL: pr20995
tic6x-elf +FAIL: pr20995
vax-netbsdelf +FAIL: pr20995
mips apparently needs a tweak to run the testcase with the right
flags.
Fixed with the change proposed here, verified across my usual set of MIPS
targets.

As this touches your TCL code in what is perhaps a non-obvious way I'll
give you 48 hours to object before I commit this to master and 2.28.
Post by Alan Modra
tic6x doesn't want to create any dynamic relocs for the testcase.
You may need to add extra flags as I did with my fix for PR ld/20828 (and
some earlier works): `-mpic -mpid=near' for GAS and `-melf32_tic6x_le' for
LD. This may be needed for some other tests recently added that fail or
have been XFAILed for `tic6x-*-*' targets. Joseph might be able to say
more or perhaps offer a patch even.
Post by Alan Modra
I don't intend to do much more on this over Christmas and New Year, so
if your favourite target is one of those that fails the test it's
likely that 2.28 will go out without the fix unless target maintainers
step up.
So I did. :)

Maciej

binutils-mips-ld-test-pr20995-cpic-fix.diff
Index: binutils/ld/testsuite/ld-elf/elf.exp
===================================================================
--- binutils.orig/ld/testsuite/ld-elf/elf.exp 2017-01-16 19:13:12.381862451 +0000
+++ binutils/ld/testsuite/ld-elf/elf.exp 2017-01-17 01:33:50.593215816 +0000
@@ -83,6 +83,13 @@ if { ![istarget hppa64*-hpux*] } {

# Only run these tests on targets that support creating shared libraries.
if { [check_shared_lib_support] } then {
+ # This target requires extra GAS options when building non-PIC code
+ # for linking with shared libraries.
+ set AFLAGS_NONPIC ""
+ if [istarget "mips*-*-*"] {
+ append AFLAGS_NONPIC " -call_nonpic"
+ }
+
# Run a test to check linking a shared library with a broken linker
# script that accidentally marks dynamic sections as notes. The
# resulting executable is not expected to work, but the linker
@@ -142,17 +149,17 @@ if { [check_shared_lib_support] } then {
}
# These targets don't copy dynamic variables into .bss.
setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*"
- run_ld_link_tests {
- {"pr20995"
- "" "tmpdir/pr20995.so" ""
- {pr20995a.s} {{readelf {-S --wide} pr20995.r}} "pr20995"}
- }
+ run_ld_link_tests [list \
+ [list \
+ "pr20995" \
+ "" "tmpdir/pr20995.so" "$AFLAGS_NONPIC" \
+ {pr20995a.s} {{readelf {-S --wide} pr20995.r}} "pr20995"]]
setup_xfail "alpha-*-*" "bfin-*-*" "ia64-*-*" "xtensa-*-*"
- run_ld_link_tests {
- {"pr20995-2"
- "" "tmpdir/pr20995-2.so" ""
- {pr20995a.s} {{readelf {-S --wide} pr20995.r}} "pr20995-2"}
- }
+ run_ld_link_tests [list \
+ [list \
+ "pr20995-2" \
+ "" "tmpdir/pr20995-2.so" "$AFLAGS_NONPIC" \
+ {pr20995a.s} {{readelf {-S --wide} pr20995.r}} "pr20995-2"]]
}

set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
Alan Modra
2017-01-18 22:18:31 UTC
Permalink
Post by Maciej W. Rozycki
As this touches your TCL code in what is perhaps a non-obvious way I'll
Looks good to me.
--
Alan Modra
Australia Development Lab, IBM
Maciej W. Rozycki
2017-01-18 23:27:50 UTC
Permalink
Post by Alan Modra
Post by Maciej W. Rozycki
As this touches your TCL code in what is perhaps a non-obvious way I'll
Looks good to me.
Thanks. Committed now then, with a description update to refer to the
original commit, and backported.

Maciej
Loading...