OSDN Git Service

2009-06-16 H.J. Lu <hongjiu.lu@intel.com>
[pf3gnuchains/pf3gnuchains3x.git] / bfd / elf-ifunc.c
1 /* ELF STT_GNU_IFUNC support.
2    Copyright 2009
3    Free Software Foundation, Inc.
4
5    This file is part of BFD, the Binary File Descriptor library.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20    MA 02110-1301, USA.  */
21
22 #include "sysdep.h"
23 #include "bfd.h"
24 #include "bfdlink.h"
25 #include "libbfd.h"
26 #define ARCH_SIZE 0
27 #include "elf-bfd.h"
28 #include "safe-ctype.h"
29 #include "libiberty.h"
30 #include "objalloc.h"
31
32 /* Create sections needed by STT_GNU_IFUNC symbol.  */
33
34 bfd_boolean
35 _bfd_elf_create_ifunc_sections (bfd *abfd, struct bfd_link_info *info)
36 {
37   flagword flags, pltflags;
38   asection *s;
39   const struct elf_backend_data *bed = get_elf_backend_data (abfd);
40   struct elf_link_hash_table *htab = elf_hash_table (info);
41
42   if (htab->irelifunc != NULL || htab->iplt != NULL)
43     return TRUE;
44
45   flags = bed->dynamic_sec_flags;
46   pltflags = flags;
47   if (bed->plt_not_loaded)
48     /* We do not clear SEC_ALLOC here because we still want the OS to
49        allocate space for the section; it's just that there's nothing
50        to read in from the object file.  */
51     pltflags &= ~ (SEC_CODE | SEC_LOAD | SEC_HAS_CONTENTS);
52   else
53     pltflags |= SEC_ALLOC | SEC_CODE | SEC_LOAD;
54   if (bed->plt_readonly)
55     pltflags |= SEC_READONLY;
56
57   if (info->shared)
58     {
59       /* We need to create .rel[a].ifunc for shared objects.  */
60       const char *rel_sec = (bed->rela_plts_and_copies_p
61                              ? ".rela.ifunc" : ".rel.ifunc");
62
63       s = bfd_make_section_with_flags (abfd, rel_sec,
64                                        flags | SEC_READONLY);
65       if (s == NULL
66           || ! bfd_set_section_alignment (abfd, s,
67                                           bed->s->log_file_align))
68         return FALSE;
69       htab->irelifunc = s;
70     }
71   else
72     {
73       /* We need to create .iplt, .rel[a].iplt, .igot and .igot.plt
74          for static executables.   */
75       s = bfd_make_section_with_flags (abfd, ".iplt", pltflags);
76       if (s == NULL
77           || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment))
78         return FALSE;
79       htab->iplt = s;
80
81       s = bfd_make_section_with_flags (abfd,
82                                        (bed->rela_plts_and_copies_p
83                                         ? ".rela.iplt" : ".rel.iplt"),
84                                        flags | SEC_READONLY);
85       if (s == NULL
86           || ! bfd_set_section_alignment (abfd, s,
87                                           bed->s->log_file_align))
88         return FALSE;
89       htab->irelplt = s;
90
91       /* We don't need the .igot section if we have the .igot.plt
92          section.  */
93       if (bed->want_got_plt)
94         s = bfd_make_section_with_flags (abfd, ".igot.plt", flags);
95       else
96         s = bfd_make_section_with_flags (abfd, ".igot", flags);
97       if (s == NULL
98           || !bfd_set_section_alignment (abfd, s,
99                                          bed->s->log_file_align))
100         return FALSE;
101       htab->igotplt = s;
102     }
103
104   return TRUE;
105 }