diff options
Diffstat (limited to 'bfd/elf-s390-common.c')
-rw-r--r-- | bfd/elf-s390-common.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/bfd/elf-s390-common.c b/bfd/elf-s390-common.c index b37cb25..032ba27 100644 --- a/bfd/elf-s390-common.c +++ b/bfd/elf-s390-common.c @@ -30,6 +30,87 @@ s390_is_ifunc_symbol_p (struct elf_link_hash_entry *h) return h->type == STT_GNU_IFUNC || eh->ifunc_resolver_address != 0; } +/* Return true if .got.plt is supposed to be emitted after .got. */ + +static inline bfd_boolean +s390_gotplt_after_got_p (struct bfd_link_info *info) +{ + struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info); + + if (!htab->elf.sgot || !htab->elf.sgotplt) + return TRUE; + + if (htab->elf.sgot->output_section == htab->elf.sgotplt->output_section) + { + if (htab->elf.sgot->output_offset < htab->elf.sgotplt->output_offset) + return TRUE; + } + else + { + if (htab->elf.sgot->output_section->vma + <= htab->elf.sgotplt->output_section->vma) + return TRUE; + } + return FALSE; +} + +/* Return the value of the _GLOBAL_OFFSET_TABLE_ symbol. */ + +static inline bfd_vma +s390_got_pointer (struct bfd_link_info *info) +{ + struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info); + bfd_vma got_pointer; + + BFD_ASSERT (htab && htab->elf.hgot); + + got_pointer = (htab->elf.hgot->root.u.def.section->output_section->vma + + htab->elf.hgot->root.u.def.section->output_offset); + /* Our ABI requires the GOT pointer to point at the very beginning + of the global offset table. */ + BFD_ASSERT (got_pointer + <= (htab->elf.sgot->output_section->vma + + htab->elf.sgot->output_offset)); + BFD_ASSERT (got_pointer + <= (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset)); + + return got_pointer; +} + + +/* Return the offset of the .got versus _GLOBAL_OFFSET_TABLE_. */ + +static inline bfd_vma +s390_got_offset (struct bfd_link_info *info) +{ + struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info); + + /* The absolute address of the .got in the target image. */ + bfd_vma got_address = (htab->elf.sgot->output_section->vma + + htab->elf.sgot->output_offset); + + /* GOT offset must not be negative. */ + BFD_ASSERT (s390_got_pointer (info) <= got_address); + return got_address - s390_got_pointer (info); +} + +/* Return the offset of the .got.plt versus _GLOBAL_OFFSET_TABLE_. */ + +static inline bfd_vma +s390_gotplt_offset (struct bfd_link_info *info) +{ + struct elf_s390_link_hash_table *htab = elf_s390_hash_table (info); + + /* The absolute address of the .got.plt in the target image. */ + bfd_vma gotplt_address = (htab->elf.sgotplt->output_section->vma + + htab->elf.sgotplt->output_offset); + + /* GOT offset must not be negative. */ + BFD_ASSERT (s390_got_pointer (info) <= gotplt_address); + return gotplt_address - s390_got_pointer (info); +} + /* Create sections needed by STT_GNU_IFUNC symbol. */ static bfd_boolean |