From 9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 13 Jan 2022 10:59:30 +1030 Subject: [PATCH] Move DT_RELR tag setting to elflink.c This makes the code setting DT_RELR tags generally available. Many targets will be able to use the defaults. Those that can't should set up sh_entsize for .relr.dyn output section before reaching the dynamic tag code in bfd_elf_final_link. * elflink.c (bfd_elf_final_link): Set up DT_RELR tags and sh_entsize. * elfxx-x86.c (_bfd_x86_elf_finish_dynamic_sections): Don't do any of that here. --- bfd/elflink.c | 53 ++++++++++++++++++++++++++++++++++++++++++++----- bfd/elfxx-x86.c | 25 ----------------------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/bfd/elflink.c b/bfd/elflink.c index 4529f83dbca..2677561478d 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -12209,7 +12209,8 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) const struct elf_backend_data *bed = get_elf_backend_data (abfd); struct elf_outext_info eoinfo; bool merged; - size_t relativecount = 0; + size_t relativecount; + size_t relr_entsize; asection *reldyn = 0; bfd_size_type amt; asection *attr_section = NULL; @@ -13053,9 +13054,24 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) o->reloc_count = 0; } + relativecount = 0; if (dynamic && info->combreloc && dynobj != NULL) relativecount = elf_link_sort_relocs (abfd, info, &reldyn); + relr_entsize = 0; + if (htab->srelrdyn != NULL + && htab->srelrdyn->output_section != NULL + && htab->srelrdyn->size != 0) + { + asection *s = htab->srelrdyn->output_section; + relr_entsize = elf_section_data (s)->this_hdr.sh_entsize; + if (relr_entsize == 0) + { + relr_entsize = bed->s->arch_size / 8; + elf_section_data (s)->this_hdr.sh_entsize = relr_entsize; + } + } + /* If we are linking against a dynamic object, or generating a shared library, finish up the dynamic linking information. */ if (dynamic) @@ -13083,17 +13099,44 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) default: continue; case DT_NULL: - if (relativecount > 0 && dyncon + bed->s->sizeof_dyn < dynconend) + if (relativecount != 0) { switch (elf_section_data (reldyn)->this_hdr.sh_type) { case SHT_REL: dyn.d_tag = DT_RELCOUNT; break; case SHT_RELA: dyn.d_tag = DT_RELACOUNT; break; - default: continue; } - dyn.d_un.d_val = relativecount; + if (dyn.d_tag != DT_NULL + && dynconend - dyncon >= bed->s->sizeof_dyn) + { + dyn.d_un.d_val = relativecount; + relativecount = 0; + break; + } relativecount = 0; - break; + } + if (relr_entsize != 0) + { + if (dynconend - dyncon >= 3 * bed->s->sizeof_dyn) + { + asection *s = htab->srelrdyn; + dyn.d_tag = DT_RELR; + dyn.d_un.d_ptr + = s->output_section->vma + s->output_offset; + bed->s->swap_dyn_out (dynobj, &dyn, dyncon); + dyncon += bed->s->sizeof_dyn; + + dyn.d_tag = DT_RELRSZ; + dyn.d_un.d_val = s->size; + bed->s->swap_dyn_out (dynobj, &dyn, dyncon); + dyncon += bed->s->sizeof_dyn; + + dyn.d_tag = DT_RELRENT; + dyn.d_un.d_val = relr_entsize; + relr_entsize = 0; + break; + } + relr_entsize = 0; } continue; diff --git a/bfd/elfxx-x86.c b/bfd/elfxx-x86.c index 119929bb093..da8a488db36 100644 --- a/bfd/elfxx-x86.c +++ b/bfd/elfxx-x86.c @@ -2388,7 +2388,6 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd, asection *sdyn; bfd_byte *dyncon, *dynconend; bfd_size_type sizeof_dyn; - bfd_size_type dt_relr_bitmap_count; bed = get_elf_backend_data (output_bfd); htab = elf_x86_hash_table (info, bed->target_id); @@ -2447,8 +2446,6 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd, if (sdyn == NULL || htab->elf.sgot == NULL) abort (); - dt_relr_bitmap_count = htab->dt_relr_bitmap.count; - sizeof_dyn = bed->s->sizeof_dyn; dyncon = sdyn->contents; dynconend = sdyn->contents + sdyn->size; @@ -2467,28 +2464,6 @@ _bfd_x86_elf_finish_dynamic_sections (bfd *output_bfd, break; continue; - case DT_NULL: - if (dt_relr_bitmap_count != 0) - { - /* Convert 3 spare dynamic tags to DT_RELR, DT_RELRSZ and - DT_RELRENT for compact relative relocation. */ - s = htab->elf.srelrdyn; - dyn.d_tag = DT_RELR; - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; - (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon); - dyncon += sizeof_dyn; - dyn.d_tag = DT_RELRSZ; - dyn.d_un.d_val = s->size; - (*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon); - dyncon += sizeof_dyn; - dyn.d_tag = DT_RELRENT; - dyn.d_un.d_val = ABI_64_P (output_bfd) ? 8 : 4; - elf_section_data (s->output_section)->this_hdr.sh_entsize - = dyn.d_un.d_val; - dt_relr_bitmap_count = 0; - } - break; - case DT_PLTGOT: s = htab->elf.sgotplt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; -- 2.30.2