| /* 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; |
| } |