diff options
Diffstat (limited to 'bfd/elf-ifunc.c')
-rw-r--r-- | bfd/elf-ifunc.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/bfd/elf-ifunc.c b/bfd/elf-ifunc.c new file mode 100644 index 0000000..4bfc31b --- /dev/null +++ b/bfd/elf-ifunc.c @@ -0,0 +1,105 @@ +/* ELF STT_GNU_IFUNC support. + Copyright 2009 + Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "bfdlink.h" +#include "libbfd.h" +#define ARCH_SIZE 0 +#include "elf-bfd.h" +#include "safe-ctype.h" +#include "libiberty.h" +#include "objalloc.h" + +/* Create sections needed by STT_GNU_IFUNC symbol. */ + +bfd_boolean +_bfd_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info) +{ + flagword flags, pltflags; + asection *s; + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + struct elf_link_hash_table *htab = elf_hash_table (info); + + if (htab->irelifunc != NULL || htab->iplt != NULL) + return TRUE; + + flags = bed->dynamic_sec_flags; + pltflags = flags; + if (bed->plt_not_loaded) + /* We do not clear SEC_ALLOC here because we still want the OS to + allocate space for the section; it's just that there's nothing + to read in from the object file. */ + pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS); + else + pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD; + if (bed->plt_readonly) + pltflags |= SEC_READONLY; + + if (info->shared) + { + /* We need to create .rel[a].ifunc for shared objects. */ + const char *rel_sec = (bed->rela_plts_and_copies_p + ? ".rela.ifunc" : ".rel.ifunc"); + + 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; + htab->irelifunc = s; + } + else + { + /* We need to create .iplt, .rel[a].iplt, .igot and .igot.plt + 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; + htab->iplt = s; + + s = bfd_make_section_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.iplt" : ".rel.iplt"), + flags | SEC_READONLY); + if (s == NULL + || ! bfd_set_section_alignment (abfd, s, + bed->s->log_file_align)) + return FALSE; + htab->irelplt = s; + + /* We don't need the .igot section if we have the .igot.plt + section. */ + if (bed->want_got_plt) + s = bfd_make_section_with_flags (abfd, ".igot.plt", flags); + 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; + htab->igotplt = s; + } + + return TRUE; +} |