diff options
author | Alan Modra <amodra@gmail.com> | 2022-01-13 10:59:30 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2022-01-13 14:12:43 +1030 |
commit | 9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588 (patch) | |
tree | b235b4cc382656f2fdc9e92832af28f08579b271 /bfd/elflink.c | |
parent | 0ae1246717ffbabda5d54be8def95f4424147c0f (diff) | |
download | fsf-binutils-gdb-9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588.zip fsf-binutils-gdb-9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588.tar.gz fsf-binutils-gdb-9c3d7d9b7ed5f442fea1ddcb41fc1e0488f51588.tar.bz2 |
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.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/bfd/elflink.c b/bfd/elflink.c index 4529f83..2677561 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; |