/* ELF STT_GNU_IFUNC support.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2009-2023 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
/* Create sections needed by STT_GNU_IFUNC symbol. */
-bfd_boolean
+bool
_bfd_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
{
flagword flags, pltflags;
struct elf_link_hash_table *htab = elf_hash_table (info);
if (htab->irelifunc != NULL || htab->iplt != NULL)
- return TRUE;
+ return true;
flags = bed->dynamic_sec_flags;
pltflags = flags;
s = bfd_make_section_with_flags (abfd, rel_sec,
flags | SEC_READONLY);
if (s == NULL
- || ! bfd_set_section_alignment (abfd, s,
- bed->s->log_file_align))
- return FALSE;
+ || !bfd_set_section_alignment (s, bed->s->log_file_align))
+ return false;
htab->irelifunc = s;
}
else
for static executables. */
s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
if (s == NULL
- || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
- return FALSE;
+ || !bfd_set_section_alignment (s, bed->plt_alignment))
+ return false;
htab->iplt = s;
s = bfd_make_section_with_flags (abfd,
? ".rela.iplt" : ".rel.iplt"),
flags | SEC_READONLY);
if (s == NULL
- || ! bfd_set_section_alignment (abfd, s,
- bed->s->log_file_align))
- return FALSE;
+ || !bfd_set_section_alignment (s, bed->s->log_file_align))
+ return false;
htab->irelplt = s;
/* We don't need the .igot section if we have the .igot.plt
else
s = bfd_make_section_with_flags (abfd, ".igot", flags);
if (s == NULL
- || !bfd_set_section_alignment (abfd, s,
- bed->s->log_file_align))
- return FALSE;
+ || !bfd_set_section_alignment (s, bed->s->log_file_align))
+ return false;
htab->igotplt = s;
}
- return TRUE;
+ return true;
}
/* Allocate space in .plt, .got and associated reloc sections for
dynamic relocs against a STT_GNU_IFUNC symbol definition. */
-bfd_boolean
+bool
_bfd_elf_allocate_ifunc_dyn_relocs (struct bfd_link_info *info,
struct elf_link_hash_entry *h,
struct elf_dyn_relocs **head,
- bfd_boolean *readonly_dynrelocs_against_ifunc_p,
unsigned int plt_entry_size,
unsigned int plt_header_size,
unsigned int got_entry_size,
- bfd_boolean avoid_plt)
+ bool avoid_plt)
{
asection *plt, *gotplt, *relplt;
struct elf_dyn_relocs *p;
unsigned int sizeof_reloc;
const struct elf_backend_data *bed;
struct elf_link_hash_table *htab;
- bfd_boolean readonly_dynrelocs_against_ifunc;
/* If AVOID_PLT is TRUE, don't use PLT if possible. */
- bfd_boolean use_plt = !avoid_plt || h->plt.refcount > 0;
- bfd_boolean need_dynreloc = !use_plt || bfd_link_pic (info);
+ bool use_plt = !avoid_plt || h->plt.refcount > 0;
+ bool need_dynreloc = !use_plt || bfd_link_pic (info);
/* When a PIC object references a STT_GNU_IFUNC symbol defined
in executable or it isn't referenced via PLT, the address of
the resolved function may be used. But in non-PIC executable,
the address of its .plt slot may be used. Pointer equality may
not work correctly. PIE or non-PLT reference should be used if
- pointer equality is required here. */
+ pointer equality is required here.
+
+ If STT_GNU_IFUNC symbol is defined in position-dependent executable,
+ backend should change it to the normal function and set its address
+ to its PLT entry which should be resolved by R_*_IRELATIVE at
+ run-time. All external references should be resolved to its PLT in
+ executable. */
if (!need_dynreloc
+ && !(bfd_link_pde (info) && h->def_regular)
&& (h->dynindx != -1
|| info->export_dynamic)
&& h->pointer_equality_needed)
h->root.root.string,
h->root.u.def.section->owner);
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ return false;
}
htab = elf_hash_table (info);
reference. */
if (need_dynreloc && h->ref_regular)
{
- bfd_boolean keep = FALSE;
+ bool keep = false;
for (p = *head; p != NULL; p = p->next)
if (p->count)
{
h->non_got_ref = 1;
/* Need dynamic relocations for non-GOT reference. */
- keep = TRUE;
+ keep = true;
if (p->pc_count)
{
/* Must use PLT for PC-relative reference. */
- use_plt = TRUE;
+ use_plt = true;
need_dynreloc = bfd_link_pic (info);
break;
}
h->got = htab->init_got_offset;
h->plt = htab->init_plt_offset;
*head = NULL;
- return TRUE;
+ return true;
}
/* Return and discard space for dynamic relocations against it if
h->got = htab->init_got_offset;
h->plt = htab->init_plt_offset;
*head = NULL;
- return TRUE;
+ return true;
}
-keep:
+ keep:
bed = get_elf_backend_data (info->output_bfd);
if (bed->rela_plts_and_copies_p)
sizeof_reloc = bed->s->sizeof_rela;
if (!need_dynreloc || !h->non_got_ref)
*head = NULL;
- readonly_dynrelocs_against_ifunc = FALSE;
-
/* Finally, allocate space. */
p = *head;
if (p != NULL)
bfd_size_type count = 0;
do
{
- if (!readonly_dynrelocs_against_ifunc)
- {
- asection *s = p->sec->output_section;
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- readonly_dynrelocs_against_ifunc = TRUE;
- }
count += p->count;
p = p->next;
}
while (p != NULL);
+ htab->ifunc_resolvers = count != 0;
+
/* Dynamic relocations are stored in
1. .rel[a].ifunc section in PIC object.
2. .rel[a].got section in dynamic executable.
}
}
- if (readonly_dynrelocs_against_ifunc_p)
- *readonly_dynrelocs_against_ifunc_p = readonly_dynrelocs_against_ifunc;
-
/* For STT_GNU_IFUNC symbol, .got.plt has the real function address
and .got has the PLT entry adddress. We will load the GOT entry
with the PLT entry in finish_dynamic_symbol if it is used. For
}
}
- return TRUE;
+ return true;
}