]> git.ipfire.org Git - thirdparty/glibc.git/blame - sysdeps/m68k/dl-machine.h
Don't use INTDEF/INTUSE with _dl_init (bug 14132).
[thirdparty/glibc.git] / sysdeps / m68k / dl-machine.h
CommitLineData
5f51e113 1/* Machine-dependent ELF dynamic relocation inline functions. m68k version.
d4697bc9 2 Copyright (C) 1996-2014 Free Software Foundation, Inc.
f1fc1823 3 This file is part of the GNU C Library.
5f51e113 4
f1fc1823 5 The GNU C Library is free software; you can redistribute it and/or
3214b89b
AJ
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.
5f51e113 9
f1fc1823
UD
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
3214b89b 13 Lesser General Public License for more details.
5f51e113 14
3214b89b 15 You should have received a copy of the GNU Lesser General Public
ab84e3ff
PE
16 License along with the GNU C Library. If not, see
17 <http://www.gnu.org/licenses/>. */
5f51e113 18
c6195ef6
RM
19#ifndef dl_machine_h
20#define dl_machine_h
21
5f51e113
RM
22#define ELF_MACHINE_NAME "m68k"
23
e9b08b88 24#include <sys/param.h>
9c986f87 25#include <sysdep.h>
40111cb9 26#include <dl-tls.h>
e9b08b88 27
f1dba308 28/* Return nonzero iff ELF header is compatible with the running host. */
5f51e113 29static inline int
f1dba308 30elf_machine_matches_host (const Elf32_Ehdr *ehdr)
5f51e113 31{
f1dba308 32 return ehdr->e_machine == EM_68K;
5f51e113
RM
33}
34
35
04d6ca32
AS
36/* Return the link-time address of _DYNAMIC.
37 This must be inlined in a function which uses global data. */
f1fc1823
UD
38static inline Elf32_Addr
39elf_machine_dynamic (void)
5f51e113 40{
04d6ca32
AS
41 Elf32_Addr addr;
42
43 asm ("move.l _DYNAMIC@GOT.w(%%a5), %0"
44 : "=a" (addr));
45 return addr;
5f51e113
RM
46}
47
48
49/* Return the run-time load address of the shared object. */
50static inline Elf32_Addr
51elf_machine_load_address (void)
52{
a9eac710 53 Elf32_Addr addr;
9c986f87 54 asm (PCREL_OP ("lea", "_dl_start", "%0", "%0", "%%pc") "\n\t"
1e0c1665 55 "sub.l _dl_start@GOT.w(%%a5), %0"
a9eac710
RM
56 : "=a" (addr));
57 return addr;
5f51e113
RM
58}
59
5f51e113
RM
60
61/* Set up the loaded object described by L so its unrelocated PLT
62 entries will jump to the on-demand fixup code in dl-runtime.c. */
63
a89c56aa 64static inline int __attribute__ ((always_inline))
482bd6c6 65elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
5f51e113
RM
66{
67 Elf32_Addr *got;
68 extern void _dl_runtime_resolve (Elf32_Word);
6e8e1d85 69 extern void _dl_runtime_profile (Elf32_Word);
5f51e113
RM
70
71 if (l->l_info[DT_JMPREL] && lazy)
72 {
73 /* The GOT entries for functions in the PLT have not yet been
74 filled in. Their initial contents will arrange when called
75 to push an offset into the .rela.plt section, push
76 _GLOBAL_OFFSET_TABLE_[1], and then jump to
77 _GLOBAL_OFFSET_TABLE_[2]. */
7189e3b8 78 got = (Elf32_Addr *) D_PTR (l, l_info[DT_PLTGOT]);
5f51e113 79 got[1] = (Elf32_Addr) l; /* Identify this shared object. */
6e8e1d85
UD
80
81 /* The got[2] entry contains the address of a function which gets
82 called to get the address of a so far unresolved function and
83 jump to it. The profiling extension of the dynamic linker allows
84 to intercept the calls to collect information. In this case we
85 don't store the address in the GOT so that all future calls also
86 end in this function. */
87 if (profile)
88 {
89 got[2] = (Elf32_Addr) &_dl_runtime_profile;
08016d92 90
00f36bfb
AS
91 if (GLRO(dl_profile) != NULL
92 && _dl_name_match_p (GLRO(dl_profile), l))
08016d92
AS
93 {
94 /* This is the object we are looking for. Say that we really
95 want profiling and the timers are started. */
f71d7f57 96 GL(dl_profile_map) = l;
08016d92 97 }
6e8e1d85
UD
98 }
99 else
100 /* This function will get called to fix up the GOT entry indicated by
101 the offset on the stack, and then jump to the resolved address. */
102 got[2] = (Elf32_Addr) &_dl_runtime_resolve;
5f51e113
RM
103 }
104
e295f619
UD
105 return lazy;
106}
107
a9eac710 108#define ELF_MACHINE_RUNTIME_FIXUP_ARGS long int save_a0, long int save_a1
e510ab5e 109#define ELF_MACHINE_RUNTIME_FIXUP_PARAMS save_a0, save_a1
5f51e113
RM
110
111
112/* Mask identifying addresses reserved for the user program,
113 where the dynamic linker should not map anything. */
114#define ELF_MACHINE_USER_ADDRESS_MASK 0x80000000UL
115
116/* Initial entry point code for the dynamic linker.
117 The C function `_dl_start' is the real entry point;
118 its return value is the user program's entry point. */
119
120#define RTLD_START asm ("\
d09d6903
AS
121 .text\n\
122 .globl _start\n\
123 .type _start,@function\n\
124_start:\n\
40111cb9 125 sub.l %fp, %fp\n\
d09d6903
AS
126 move.l %sp, -(%sp)\n\
127 jbsr _dl_start\n\
128 addq.l #4, %sp\n\
129 /* FALLTHRU */\n\
130\n\
131 .globl _dl_start_user\n\
132 .type _dl_start_user,@function\n\
133_dl_start_user:\n\
134 | Save the user entry point address in %a4.\n\
135 move.l %d0, %a4\n\
d09d6903
AS
136 | See if we were run as a command with the executable file\n\
137 | name as an extra leading argument.\n\
9c986f87 138 " PCREL_OP ("move.l", "_dl_skip_args", "%d0", "%d0", "%pc") "\n\
d09d6903
AS
139 | Pop the original argument count\n\
140 move.l (%sp)+, %d1\n\
141 | Subtract _dl_skip_args from it.\n\
142 sub.l %d0, %d1\n\
143 | Adjust the stack pointer to skip _dl_skip_args words.\n\
144 lea (%sp, %d0*4), %sp\n\
145 | Push back the modified argument count.\n\
146 move.l %d1, -(%sp)\n\
147 # Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
148 pea 8(%sp, %d1*4)\n\
149 pea 8(%sp)\n\
150 move.l %d1, -(%sp)\n\
9c986f87 151 " PCREL_OP ("move.l", "_rtld_local", "-(%sp)", "%d0", "%pc") "\n\
c5684fdb 152 jbsr _dl_init@PLTPC\n\
d09d6903
AS
153 addq.l #8, %sp\n\
154 addq.l #8, %sp\n\
155 | Pass our finalizer function to the user in %a1.\n\
9c986f87 156 " PCREL_OP ("lea", "_dl_fini", "%a1", "%a1", "%pc") "\n\
d09d6903
AS
157 | Initialize %fp with the stack pointer.\n\
158 move.l %sp, %fp\n\
159 | Jump to the user's entry point.\n\
160 jmp (%a4)\n\
161 .size _dl_start_user, . - _dl_start_user\n\
c0d5b73e 162 .previous");
c6195ef6 163
40111cb9
MK
164/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
165 TLS variable, so undefined references should not be allowed to
166 define the value.
5c6029e5
UD
167 ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
168 of the main executable's symbols, as for a COPY reloc. */
169#define elf_machine_type_class(type) \
40111cb9
MK
170 ((((type) == R_68K_JMP_SLOT \
171 || (type) == R_68K_TLS_DTPMOD32 \
172 || (type) == R_68K_TLS_DTPREL32 \
173 || (type) == R_68K_TLS_TPREL32) * ELF_RTYPE_CLASS_PLT) \
5c6029e5 174 | (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY))
fea9a86a
UD
175
176/* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
ff91cf30 177#define ELF_MACHINE_JMP_SLOT R_68K_JMP_SLOT
c6195ef6
RM
178
179/* The m68k never uses Elf32_Rel relocations. */
180#define ELF_MACHINE_NO_REL 1
4cf5b6d0 181#define ELF_MACHINE_NO_RELA 0
c6195ef6 182
408c9db5
UD
183static inline Elf32_Addr
184elf_machine_fixup_plt (struct link_map *map, lookup_t t,
185 const Elf32_Rela *reloc,
ff91cf30
UD
186 Elf32_Addr *reloc_addr, Elf32_Addr value)
187{
408c9db5 188 return *reloc_addr = value;
98916642
UD
189}
190
191/* Return the final value of a plt relocation. On the m68k the JMP_SLOT
192 relocation ignores the addend. */
193static inline Elf32_Addr
194elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
195 Elf32_Addr value)
196{
197 return value;
ff91cf30
UD
198}
199
00f36bfb
AS
200/* Names of the architecture-specific auditing callback functions. */
201#define ARCH_LA_PLTENTER m68k_gnu_pltenter
202#define ARCH_LA_PLTEXIT m68k_gnu_pltexit
203
c6195ef6
RM
204#endif /* !dl_machine_h */
205
00f36bfb 206#ifdef RESOLVE_MAP
c6195ef6
RM
207
208/* Perform the relocation specified by RELOC and SYM (which is fully resolved).
209 MAP is the object containing the reloc. */
210
7618b354 211auto inline void __attribute__ ((unused, always_inline))
4ead5e71 212elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
482bd6c6 213 const Elf32_Sym *sym, const struct r_found_version *version,
5c3bd235 214 void *const reloc_addr_arg, int skip_ifunc)
c6195ef6 215{
5027ae10 216 Elf32_Addr *const reloc_addr = reloc_addr_arg;
85bdccdb
UD
217 const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
218
219 if (__builtin_expect (r_type == R_68K_RELATIVE, 0))
fea9a86a
UD
220 *reloc_addr = map->l_addr + reloc->r_addend;
221 else
c6195ef6 222 {
e9b08b88 223 const Elf32_Sym *const refsym = sym;
00f36bfb
AS
224 struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
225 Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
fea9a86a 226
85bdccdb 227 switch (r_type)
fea9a86a
UD
228 {
229 case R_68K_COPY:
c96df8ef
UD
230 if (sym == NULL)
231 /* This can happen in trace mode if an object could not be
232 found. */
233 break;
b5fba1ad 234 if (sym->st_size > refsym->st_size
cebbd6e7 235 || (sym->st_size < refsym->st_size && GLRO(dl_verbose)))
e9b08b88
UD
236 {
237 const char *strtab;
238
7189e3b8 239 strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
773b6400
UD
240 _dl_error_printf ("\
241%s: Symbol `%s' has different size in shared object, consider re-linking\n",
b9375348 242 RTLD_PROGNAME, strtab + refsym->st_name);
e9b08b88 243 }
5027ae10
AO
244 memcpy (reloc_addr_arg, (void *) value,
245 MIN (sym->st_size, refsym->st_size));
fea9a86a
UD
246 break;
247 case R_68K_GLOB_DAT:
248 case R_68K_JMP_SLOT:
98916642 249 *reloc_addr = value;
fea9a86a
UD
250 break;
251 case R_68K_8:
252 *(char *) reloc_addr = value + reloc->r_addend;
253 break;
254 case R_68K_16:
255 *(short *) reloc_addr = value + reloc->r_addend;
256 break;
257 case R_68K_32:
258 *reloc_addr = value + reloc->r_addend;
259 break;
260 case R_68K_PC8:
261 *(char *) reloc_addr
262 = value + reloc->r_addend - (Elf32_Addr) reloc_addr;
263 break;
264 case R_68K_PC16:
265 *(short *) reloc_addr
266 = value + reloc->r_addend - (Elf32_Addr) reloc_addr;
267 break;
268 case R_68K_PC32:
269 *reloc_addr = value + reloc->r_addend - (Elf32_Addr) reloc_addr;
270 break;
57d2b48d 271#ifndef RTLD_BOOTSTRAP
40111cb9
MK
272 case R_68K_TLS_DTPMOD32:
273 /* Get the information from the link map returned by the
274 resolv function. */
275 if (sym_map != NULL)
276 *reloc_addr = sym_map->l_tls_modid;
277 break;
278 case R_68K_TLS_DTPREL32:
279 if (sym != NULL)
280 *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);
281 break;
282 case R_68K_TLS_TPREL32:
283 if (sym != NULL)
284 {
285 CHECK_STATIC_TLS (map, sym_map);
286 *reloc_addr = TLS_TPREL_VALUE (sym_map, sym, reloc);
287 }
288 break;
57d2b48d 289#endif /* !RTLD_BOOTSTRAP */
fea9a86a
UD
290 case R_68K_NONE: /* Alright, Wilbur. */
291 break;
292 default:
85bdccdb 293 _dl_reloc_bad_type (map, r_type, 0);
fea9a86a
UD
294 break;
295 }
c6195ef6 296 }
c6195ef6
RM
297}
298
7618b354 299auto inline void __attribute__ ((unused, always_inline))
638c8659 300elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
5027ae10 301 void *const reloc_addr_arg)
85bdccdb 302{
5027ae10 303 Elf32_Addr *const reloc_addr = reloc_addr_arg;
85bdccdb
UD
304 *reloc_addr = l_addr + reloc->r_addend;
305}
306
7618b354 307auto inline void __attribute__ ((unused, always_inline))
893f3d10 308elf_machine_lazy_rel (struct link_map *map,
5c3bd235
AS
309 Elf32_Addr l_addr, const Elf32_Rela *reloc,
310 int skip_ifunc)
c6195ef6 311{
68d11b26 312 Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
893f3d10
RM
313 if (ELF32_R_TYPE (reloc->r_info) == R_68K_JMP_SLOT)
314 *reloc_addr += l_addr;
315 else
316 _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
c6195ef6
RM
317}
318
00f36bfb 319#endif /* RESOLVE_MAP */