This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: dynrelro section for read-only dynamic symbols copied into executable


On 26 December 2016 at 06:44, Alan Modra <amodra@gmail.com> wrote:
> 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

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


> 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]