Remove divide from _ELF_DYNAMIC_DO_RELOC in elf/dynamic-link.h.
[platform/upstream/glibc.git] / elf / dynamic-link.h
1 /* Inline functions for dynamic linking.
2    Copyright (C) 1995-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
18
19 /* This macro is used as a callback from elf_machine_rel{a,} when a
20    static TLS reloc is about to be performed.  Since (in dl-load.c) we
21    permit dynamic loading of objects that might use such relocs, we
22    have to check whether each use is actually doable.  If the object
23    whose TLS segment the reference resolves to was allocated space in
24    the static TLS block at startup, then it's ok.  Otherwise, we make
25    an attempt to allocate it in surplus space on the fly.  If that
26    can't be done, we fall back to the error that DF_STATIC_TLS is
27    intended to produce.  */
28 #define CHECK_STATIC_TLS(map, sym_map)                                  \
29     do {                                                                \
30       if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET    \
31                             || ((sym_map)->l_tls_offset                 \
32                                 == FORCED_DYNAMIC_TLS_OFFSET), 0))      \
33         _dl_allocate_static_tls (sym_map);                              \
34     } while (0)
35
36 #define TRY_STATIC_TLS(map, sym_map)                                    \
37     (__builtin_expect ((sym_map)->l_tls_offset                          \
38                        != FORCED_DYNAMIC_TLS_OFFSET, 1)                 \
39      && (__builtin_expect ((sym_map)->l_tls_offset != NO_TLS_OFFSET, 1) \
40          || _dl_try_allocate_static_tls (sym_map) == 0))
41
42 int internal_function _dl_try_allocate_static_tls (struct link_map *map);
43
44 #include <elf.h>
45
46 #ifdef RESOLVE_MAP
47 /* We pass reloc_addr as a pointer to void, as opposed to a pointer to
48    ElfW(Addr), because not all architectures can assume that the
49    relocated address is properly aligned, whereas the compiler is
50    entitled to assume that a pointer to a type is properly aligned for
51    the type.  Even if we cast the pointer back to some other type with
52    less strict alignment requirements, the compiler might still
53    remember that the pointer was originally more aligned, thereby
54    optimizing away alignment tests or using word instructions for
55    copying memory, breaking the very code written to handle the
56    unaligned cases.  */
57 # if ! ELF_MACHINE_NO_REL
58 auto inline void __attribute__((always_inline))
59 elf_machine_rel (struct link_map *map, const ElfW(Rel) *reloc,
60                  const ElfW(Sym) *sym, const struct r_found_version *version,
61                  void *const reloc_addr, int skip_ifunc);
62 auto inline void __attribute__((always_inline))
63 elf_machine_rel_relative (ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
64                           void *const reloc_addr);
65 # endif
66 # if ! ELF_MACHINE_NO_RELA
67 auto inline void __attribute__((always_inline))
68 elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
69                   const ElfW(Sym) *sym, const struct r_found_version *version,
70                   void *const reloc_addr, int skip_ifunc);
71 auto inline void __attribute__((always_inline))
72 elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
73                            void *const reloc_addr);
74 # endif
75 # if ELF_MACHINE_NO_RELA || defined ELF_MACHINE_PLT_REL
76 auto inline void __attribute__((always_inline))
77 elf_machine_lazy_rel (struct link_map *map,
78                       ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
79                       int skip_ifunc);
80 # else
81 auto inline void __attribute__((always_inline))
82 elf_machine_lazy_rel (struct link_map *map,
83                       ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
84                       int skip_ifunc);
85 # endif
86 #endif
87
88 #include <dl-machine.h>
89
90 #include "get-dynamic-info.h"
91
92 #ifdef RESOLVE_MAP
93
94 # ifdef RTLD_BOOTSTRAP
95 #  define ELF_DURING_STARTUP (1)
96 # else
97 #  define ELF_DURING_STARTUP (0)
98 # endif
99
100 /* Get the definitions of `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.
101    These functions are almost identical, so we use cpp magic to avoid
102    duplicating their code.  It cannot be done in a more general function
103    because we must be able to completely inline.  */
104
105 /* On some machines, notably SPARC, DT_REL* includes DT_JMPREL in its
106    range.  Note that according to the ELF spec, this is completely legal!
107
108    We are guarenteed that we have one of three situations.  Either DT_JMPREL
109    comes immediately after DT_REL*, or there is overlap and DT_JMPREL
110    consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
111    are completely separate and there is a gap between them.  */
112
113 # define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, do_lazy, skip_ifunc, test_rel) \
114   do {                                                                        \
115     struct { ElfW(Addr) start, size;                                          \
116              __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; }  \
117       ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };                         \
118                                                                               \
119     if ((map)->l_info[DT_##RELOC])                                            \
120       {                                                                       \
121         ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]);                  \
122         ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val;           \
123         if (map->l_info[VERSYMIDX (DT_##RELOC##COUNT)] != NULL)               \
124           ranges[0].nrelative                                                 \
125             = map->l_info[VERSYMIDX (DT_##RELOC##COUNT)]->d_un.d_val;         \
126       }                                                                       \
127     if ((map)->l_info[DT_PLTREL]                                              \
128         && (!test_rel || (map)->l_info[DT_PLTREL]->d_un.d_val == DT_##RELOC)) \
129       {                                                                       \
130         ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]);                  \
131         ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val;             \
132                                                                               \
133         if (ranges[0].start + ranges[0].size == (start + size))               \
134           ranges[0].size -= size;                                             \
135         if (! ELF_DURING_STARTUP && ((do_lazy) || ranges[0].size == 0))       \
136           {                                                                   \
137             ranges[1].start = start;                                          \
138             ranges[1].size = size;                                            \
139             ranges[1].lazy = (do_lazy);                                       \
140           }                                                                   \
141         else                                                                  \
142           {                                                                   \
143             /* Combine processing the sections.  */                           \
144             ranges[0].size += size;                                           \
145           }                                                                   \
146       }                                                                       \
147                                                                               \
148     if (ELF_DURING_STARTUP)                                                   \
149       elf_dynamic_do_##reloc ((map), ranges[0].start, ranges[0].size,         \
150                               ranges[0].nrelative, 0, skip_ifunc);            \
151     else                                                                      \
152       {                                                                       \
153         int ranges_index;                                                     \
154         for (ranges_index = 0; ranges_index < 2; ++ranges_index)              \
155           elf_dynamic_do_##reloc ((map),                                      \
156                                   ranges[ranges_index].start,                 \
157                                   ranges[ranges_index].size,                  \
158                                   ranges[ranges_index].nrelative,             \
159                                   ranges[ranges_index].lazy,                  \
160                                   skip_ifunc);                                \
161       }                                                                       \
162   } while (0)
163
164 # if ELF_MACHINE_NO_REL || ELF_MACHINE_NO_RELA
165 #  define _ELF_CHECK_REL 0
166 # else
167 #  define _ELF_CHECK_REL 1
168 # endif
169
170 # if ! ELF_MACHINE_NO_REL
171 #  include "do-rel.h"
172 #  define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) \
173   _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, lazy, skip_ifunc, _ELF_CHECK_REL)
174 # else
175 #  define ELF_DYNAMIC_DO_REL(map, lazy, skip_ifunc) /* Nothing to do.  */
176 # endif
177
178 # if ! ELF_MACHINE_NO_RELA
179 #  define DO_RELA
180 #  include "do-rel.h"
181 #  define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) \
182   _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, lazy, skip_ifunc, _ELF_CHECK_REL)
183 # else
184 #  define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc) /* Nothing to do.  */
185 # endif
186
187 /* This can't just be an inline function because GCC is too dumb
188    to inline functions containing inlines themselves.  */
189 # define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc) \
190   do {                                                                        \
191     int edr_lazy = elf_machine_runtime_setup ((map), (lazy),                  \
192                                               (consider_profile));            \
193     ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc);                         \
194     ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc);                        \
195   } while (0)
196
197 #endif