summaryrefslogtreecommitdiff
path: root/bfd/elflink.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2022-01-13 10:59:30 +1030
committerAlan Modra <amodra@gmail.com>2022-01-13 14:12:43 +1030
commit9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588 (patch)
treeb235b4cc382656f2fdc9e92832af28f08579b271 /bfd/elflink.c
parent0ae1246717ffbabda5d54be8def95f4424147c0f (diff)
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.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r--bfd/elflink.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 4529f83dbc..2677561478 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;