Update.
[glibc.git] / sysdeps / alpha / dl-machine.h
blob2b15e33518d593f0e06a308437e705125b409049
1 /* Machine-dependent ELF dynamic relocation inline functions. Alpha version.
2 Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Richard Henderson <rth@tamu.edu>.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, write to the Free
18 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA. */
21 /* This was written in the absence of an ABI -- don't expect
22 it to remain unchanged. */
24 #ifndef dl_machine_h
25 #define dl_machine_h 1
27 #define ELF_MACHINE_NAME "alpha"
29 #include <string.h>
32 /* Mask identifying addresses reserved for the user program,
33 where the dynamic linker should not map anything. */
34 #define ELF_MACHINE_USER_ADDRESS_MASK 0x120000000UL
36 /* Return nonzero iff ELF header is compatible with the running host. */
37 static inline int
38 elf_machine_matches_host (const Elf64_Ehdr *ehdr)
40 return ehdr->e_machine == EM_ALPHA;
43 /* Return the link-time address of _DYNAMIC. The multiple-got-capable
44 linker no longer allocates the first .got entry for this. But not to
45 worry, no special tricks are needed. */
46 static inline Elf64_Addr
47 elf_machine_dynamic (void)
49 #ifndef NO_AXP_MULTI_GOT_LD
50 return (Elf64_Addr) &_DYNAMIC;
51 #else
52 register Elf64_Addr *gp __asm__ ("$29");
53 return gp[-4096];
54 #endif
57 /* Return the run-time load address of the shared object. */
58 static inline Elf64_Addr
59 elf_machine_load_address (void)
61 /* NOTE: While it is generally unfriendly to put data in the text
62 segment, it is only slightly less so when the "data" is an
63 instruction. While we don't have to worry about GLD just yet, an
64 optimizing linker might decide that our "data" is an unreachable
65 instruction and throw it away -- with the right switches, DEC's
66 linker will do this. What ought to happen is we should add
67 something to GAS to allow us access to the new GPREL_HI32/LO32
68 relocation types stolen from OSF/1 3.0. */
69 /* This code relies on the fact that BRADDR relocations do not
70 appear in dynamic relocation tables. Not that that would be very
71 useful anyway -- br/bsr has a 4MB range and the shared libraries
72 are usually many many terabytes away. */
74 Elf64_Addr dot;
75 long int zero_disp;
77 asm("br %0, 1f\n"
78 "0:\n\t"
79 "br $0, 2f\n"
80 "1:\n\t"
81 ".section\t.data\n"
82 "2:\n\t"
83 ".quad 0b\n\t"
84 ".previous"
85 : "=r"(dot));
87 zero_disp = *(int *) dot;
88 zero_disp = (zero_disp << 43) >> 41;
90 return dot - *(Elf64_Addr *) (dot + 4 + zero_disp);
93 /* Set up the loaded object described by L so its unrelocated PLT
94 entries will jump to the on-demand fixup code in dl-runtime.c. */
96 static inline int
97 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
99 Elf64_Addr plt;
100 extern void _dl_runtime_resolve (void);
101 extern void _dl_runtime_profile (void);
103 if (l->l_info[DT_JMPREL] && lazy)
105 /* The GOT entries for the functions in the PLT have not been
106 filled in yet. Their initial contents are directed to the
107 PLT which arranges for the dynamic linker to be called. */
108 plt = D_PTR (l, l_info[DT_PLTGOT]);
110 /* This function will be called to perform the relocation. */
111 if (!profile)
112 *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve;
113 else
115 *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_profile;
117 if (_dl_name_match_p (GL(dl_profile), l))
119 /* This is the object we are looking for. Say that we really
120 want profiling and the timers are started. */
121 GL(dl_profile_map) = l;
125 /* Identify this shared object */
126 *(Elf64_Addr *)(plt + 24) = (Elf64_Addr) l;
128 /* If the first instruction of the plt entry is not
129 "br $28, plt0", we have to reinitialize .plt for lazy relocation. */
130 if (*(unsigned int *)(plt + 32) != 0xc39ffff7)
132 unsigned int val = 0xc39ffff7;
133 unsigned int *slot, *end;
134 const Elf64_Rela *rela = (const Elf64_Rela *)
135 D_PTR (l, l_info[DT_JMPREL]);
136 Elf64_Addr l_addr = l->l_addr;
138 /* br t12,.+4; ldq t12,12(t12); nop; jmp t12,(t12),.+4 */
139 *(unsigned long *)plt = 0xa77b000cc3600000;
140 *(unsigned long *)(plt + 8) = 0x6b7b000047ff041f;
141 slot = (unsigned int *)(plt + 32);
142 end = (unsigned int *)(plt + 32
143 + l->l_info[DT_PLTRELSZ]->d_un.d_val / 2);
144 while (slot < end)
146 /* br at,.plt+0 */
147 *slot = val;
148 *(Elf64_Addr *) rela->r_offset = (Elf64_Addr) slot - l_addr;
149 val -= 3;
150 slot += 3;
151 ++rela;
156 return lazy;
159 /* This code is used in dl-runtime.c to call the `fixup' function
160 and then redirect to the address it returns. */
161 #define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name, IMB) \
162 extern void tramp_name (void); \
163 asm ( "\
164 .globl " #tramp_name " \n\
165 .ent " #tramp_name " \n\
166 " #tramp_name ": \n\
167 lda $sp, -44*8($sp) \n\
168 .frame $sp, 44*8, $26 \n\
169 /* Preserve all integer registers that C normally \n\
170 doesn't. */ \n\
171 stq $26, 0*8($sp) \n\
172 stq $0, 1*8($sp) \n\
173 stq $1, 2*8($sp) \n\
174 stq $2, 3*8($sp) \n\
175 stq $3, 4*8($sp) \n\
176 stq $4, 5*8($sp) \n\
177 stq $5, 6*8($sp) \n\
178 stq $6, 7*8($sp) \n\
179 stq $7, 8*8($sp) \n\
180 stq $8, 9*8($sp) \n\
181 stq $16, 10*8($sp) \n\
182 stq $17, 11*8($sp) \n\
183 stq $18, 12*8($sp) \n\
184 stq $19, 13*8($sp) \n\
185 stq $20, 14*8($sp) \n\
186 stq $21, 15*8($sp) \n\
187 stq $22, 16*8($sp) \n\
188 stq $23, 17*8($sp) \n\
189 stq $24, 18*8($sp) \n\
190 stq $25, 19*8($sp) \n\
191 stq $29, 20*8($sp) \n\
192 stt $f0, 21*8($sp) \n\
193 stt $f1, 22*8($sp) \n\
194 stt $f10, 23*8($sp) \n\
195 stt $f11, 24*8($sp) \n\
196 stt $f12, 25*8($sp) \n\
197 stt $f13, 26*8($sp) \n\
198 stt $f14, 27*8($sp) \n\
199 stt $f15, 28*8($sp) \n\
200 stt $f16, 29*8($sp) \n\
201 stt $f17, 30*8($sp) \n\
202 stt $f18, 31*8($sp) \n\
203 stt $f19, 32*8($sp) \n\
204 stt $f20, 33*8($sp) \n\
205 stt $f21, 34*8($sp) \n\
206 stt $f22, 35*8($sp) \n\
207 stt $f23, 36*8($sp) \n\
208 stt $f24, 37*8($sp) \n\
209 stt $f25, 38*8($sp) \n\
210 stt $f26, 39*8($sp) \n\
211 stt $f27, 40*8($sp) \n\
212 stt $f28, 41*8($sp) \n\
213 stt $f29, 42*8($sp) \n\
214 stt $f30, 43*8($sp) \n\
215 .mask 0x27ff01ff, -44*8 \n\
216 .fmask 0xfffffc03, -(44-21)*8 \n\
217 /* Set up our $gp */ \n\
218 br $gp, .+4 \n\
219 ldgp $gp, 0($gp) \n\
220 .prologue 0 \n\
221 /* Set up the arguments for fixup: */ \n\
222 /* $16 = link_map out of plt0 */ \n\
223 /* $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24 */\n\
224 /* $18 = return address */ \n\
225 subq $28, $27, $17 \n\
226 ldq $16, 8($27) \n\
227 subq $17, 20, $17 \n\
228 mov $26, $18 \n\
229 addq $17, $17, $17 \n\
230 /* Do the fixup */ \n\
231 bsr $26, " ASM_ALPHA_NG_SYMBOL_PREFIX #fixup_name "..ng\n\
232 /* Move the destination address into position. */ \n\
233 mov $0, $27 \n\
234 /* Restore program registers. */ \n\
235 ldq $26, 0*8($sp) \n\
236 ldq $0, 1*8($sp) \n\
237 ldq $1, 2*8($sp) \n\
238 ldq $2, 3*8($sp) \n\
239 ldq $3, 4*8($sp) \n\
240 ldq $4, 5*8($sp) \n\
241 ldq $5, 6*8($sp) \n\
242 ldq $6, 7*8($sp) \n\
243 ldq $7, 8*8($sp) \n\
244 ldq $8, 9*8($sp) \n\
245 ldq $16, 10*8($sp) \n\
246 ldq $17, 11*8($sp) \n\
247 ldq $18, 12*8($sp) \n\
248 ldq $19, 13*8($sp) \n\
249 ldq $20, 14*8($sp) \n\
250 ldq $21, 15*8($sp) \n\
251 ldq $22, 16*8($sp) \n\
252 ldq $23, 17*8($sp) \n\
253 ldq $24, 18*8($sp) \n\
254 ldq $25, 19*8($sp) \n\
255 ldq $29, 20*8($sp) \n\
256 ldt $f0, 21*8($sp) \n\
257 ldt $f1, 22*8($sp) \n\
258 ldt $f10, 23*8($sp) \n\
259 ldt $f11, 24*8($sp) \n\
260 ldt $f12, 25*8($sp) \n\
261 ldt $f13, 26*8($sp) \n\
262 ldt $f14, 27*8($sp) \n\
263 ldt $f15, 28*8($sp) \n\
264 ldt $f16, 29*8($sp) \n\
265 ldt $f17, 30*8($sp) \n\
266 ldt $f18, 31*8($sp) \n\
267 ldt $f19, 32*8($sp) \n\
268 ldt $f20, 33*8($sp) \n\
269 ldt $f21, 34*8($sp) \n\
270 ldt $f22, 35*8($sp) \n\
271 ldt $f23, 36*8($sp) \n\
272 ldt $f24, 37*8($sp) \n\
273 ldt $f25, 38*8($sp) \n\
274 ldt $f26, 39*8($sp) \n\
275 ldt $f27, 40*8($sp) \n\
276 ldt $f28, 41*8($sp) \n\
277 ldt $f29, 42*8($sp) \n\
278 ldt $f30, 43*8($sp) \n\
279 /* Flush the Icache after having modified the .plt code. */\n\
280 " #IMB " \n\
281 /* Clean up and turn control to the destination */ \n\
282 lda $sp, 44*8($sp) \n\
283 jmp $31, ($27) \n\
284 .end " #tramp_name)
286 #ifndef PROF
287 #define ELF_MACHINE_RUNTIME_TRAMPOLINE \
288 TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup, imb); \
289 TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup, /* nop */);
290 #else
291 #define ELF_MACHINE_RUNTIME_TRAMPOLINE \
292 TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup, imb); \
293 strong_alias (_dl_runtime_resolve, _dl_runtime_profile);
294 #endif
296 /* Initial entry point code for the dynamic linker.
297 The C function `_dl_start' is the real entry point;
298 its return value is the user program's entry point. */
300 #define RTLD_START asm ("\
301 .section .text \n\
302 .set at \n\
303 .globl _start \n\
304 .ent _start \n\
305 _start: \n\
306 br $gp, 0f \n\
307 0: ldgp $gp, 0($gp) \n\
308 .prologue 0 \n\
309 /* Pass pointer to argument block to _dl_start. */ \n\
310 mov $sp, $16 \n\
311 bsr $26, "ASM_ALPHA_NG_SYMBOL_PREFIX"_dl_start..ng \n\
312 .end _start \n\
313 /* FALLTHRU */ \n\
314 .globl _dl_start_user \n\
315 .ent _dl_start_user \n\
316 _dl_start_user: \n\
317 .frame $30,0,$31,0 \n\
318 .prologue 0 \n\
319 /* Save the user entry point address in s0. */ \n\
320 mov $0, $9 \n\
321 /* Store the highest stack address. */ \n\
322 stq $30, __libc_stack_end \n\
323 /* See if we were run as a command with the executable \n\
324 file name as an extra leading argument. */ \n\
325 ldl $1, _dl_skip_args \n\
326 bne $1, $fixup_stack \n\
327 $fixup_stack_ret: \n\
328 /* The special initializer gets called with the stack \n\
329 just as the application's entry point will see it; \n\
330 it can switch stacks if it moves these contents \n\
331 over. */ \n\
332 " RTLD_START_SPECIAL_INIT " \n\
333 /* Call _dl_init(_dl_loaded, argc, argv, envp) to run \n\
334 initializers. */ \n\
335 ldq $16, _rtld_local \n\
336 ldq $17, 0($sp) \n\
337 lda $18, 8($sp) \n\
338 s8addq $17, 8, $19 \n\
339 addq $19, $18, $19 \n\
340 jsr $26, _dl_init_internal \n\
341 /* Pass our finalizer function to the user in $0. */ \n\
342 lda $0, _dl_fini \n\
343 /* Jump to the user's entry point. */ \n\
344 mov $9, $27 \n\
345 jmp ($9) \n\
346 $fixup_stack: \n\
347 /* Adjust the stack pointer to skip _dl_skip_args words.\n\
348 This involves copying everything down, since the \n\
349 stack pointer must always be 16-byte aligned. */ \n\
350 ldq $2, 0($sp) \n\
351 ldq $5, _dl_argv \n\
352 subq $31, $1, $6 \n\
353 subq $2, $1, $2 \n\
354 s8addq $6, $5, $5 \n\
355 mov $sp, $4 \n\
356 s8addq $1, $sp, $3 \n\
357 stq $2, 0($sp) \n\
358 stq $5, _dl_argv \n\
359 /* Copy down argv. */ \n\
360 0: ldq $5, 8($3) \n\
361 addq $4, 8, $4 \n\
362 addq $3, 8, $3 \n\
363 stq $5, 0($4) \n\
364 bne $5, 0b \n\
365 /* Copy down envp. */ \n\
366 1: ldq $5, 8($3) \n\
367 addq $4, 8, $4 \n\
368 addq $3, 8, $3 \n\
369 stq $5, 0($4) \n\
370 bne $5, 1b \n\
371 /* Copy down auxiliary table. */ \n\
372 2: ldq $5, 8($3) \n\
373 ldq $6, 16($3) \n\
374 addq $4, 16, $4 \n\
375 addq $3, 16, $3 \n\
376 stq $5, -8($4) \n\
377 stq $6, 0($4) \n\
378 bne $5, 2b \n\
379 br $fixup_stack_ret \n\
380 .end _dl_start_user \n\
381 .set noat \n\
382 .previous");
384 #ifndef RTLD_START_SPECIAL_INIT
385 #define RTLD_START_SPECIAL_INIT /* nothing */
386 #endif
388 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
389 PLT entries should not be allowed to define the value.
390 ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
391 of the main executable's symbols, as for a COPY reloc, which we don't
392 use. */
393 #define elf_machine_type_class(type) \
394 (((type) == R_ALPHA_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
396 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */
397 #define ELF_MACHINE_JMP_SLOT R_ALPHA_JMP_SLOT
399 /* The alpha never uses Elf64_Rel relocations. */
400 #define ELF_MACHINE_NO_REL 1
402 /* Fix up the instructions of a PLT entry to invoke the function
403 rather than the dynamic linker. */
404 static inline Elf64_Addr
405 elf_machine_fixup_plt (struct link_map *l, lookup_t t,
406 const Elf64_Rela *reloc,
407 Elf64_Addr *got_addr, Elf64_Addr value)
409 const Elf64_Rela *rela_plt;
410 Elf64_Word *plte;
411 long int edisp;
413 /* Store the value we are going to load. */
414 *got_addr = value;
416 /* Recover the PLT entry address by calculating reloc's index into the
417 .rela.plt, and finding that entry in the .plt. */
418 rela_plt = (void *) D_PTR (l, l_info[DT_JMPREL]);
419 plte = (void *) (D_PTR (l, l_info[DT_PLTGOT]) + 32);
420 plte += 3 * (reloc - rela_plt);
422 /* Find the displacement from the plt entry to the function. */
423 edisp = (long int) (value - (Elf64_Addr)&plte[3]) / 4;
425 if (edisp >= -0x100000 && edisp < 0x100000)
427 /* If we are in range, use br to perfect branch prediction and
428 elide the dependency on the address load. This case happens,
429 e.g., when a shared library call is resolved to the same library. */
431 int hi, lo;
432 hi = value - (Elf64_Addr)&plte[0];
433 lo = (short int) hi;
434 hi = (hi - lo) >> 16;
436 /* Emit "lda $27,lo($27)" */
437 plte[1] = 0x237b0000 | (lo & 0xffff);
439 /* Emit "br $31,function" */
440 plte[2] = 0xc3e00000 | (edisp & 0x1fffff);
442 /* Think about thread-safety -- the previous instructions must be
443 committed to memory before the first is overwritten. */
444 __asm__ __volatile__("wmb" : : : "memory");
446 /* Emit "ldah $27,hi($27)" */
447 plte[0] = 0x277b0000 | (hi & 0xffff);
449 else
451 /* Don't bother with the hint since we already know the hint is
452 wrong. Eliding it prevents the wrong page from getting pulled
453 into the cache. */
455 int hi, lo;
456 hi = (Elf64_Addr)got_addr - (Elf64_Addr)&plte[0];
457 lo = (short)hi;
458 hi = (hi - lo) >> 16;
460 /* Emit "ldq $27,lo($27)" */
461 plte[1] = 0xa77b0000 | (lo & 0xffff);
463 /* Emit "jmp $31,($27)" */
464 plte[2] = 0x6bfb0000;
466 /* Think about thread-safety -- the previous instructions must be
467 committed to memory before the first is overwritten. */
468 __asm__ __volatile__("wmb" : : : "memory");
470 /* Emit "ldah $27,hi($27)" */
471 plte[0] = 0x277b0000 | (hi & 0xffff);
474 /* At this point, if we've been doing runtime resolution, Icache is dirty.
475 This will be taken care of in _dl_runtime_resolve. If instead we are
476 doing this as part of non-lazy startup relocation, that bit of code
477 hasn't made it into Icache yet, so there's nothing to clean up. */
479 return value;
482 /* Return the final value of a plt relocation. */
483 static inline Elf64_Addr
484 elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
485 Elf64_Addr value)
487 return value + reloc->r_addend;
490 #endif /* !dl_machine_h */
492 #ifdef RESOLVE
494 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
495 MAP is the object containing the reloc. */
496 static inline void
497 elf_machine_rela (struct link_map *map,
498 const Elf64_Rela *reloc,
499 const Elf64_Sym *sym,
500 const struct r_found_version *version,
501 Elf64_Addr *const reloc_addr)
503 unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
505 #if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC && !defined SHARED
506 /* This is defined in rtld.c, but nowhere in the static libc.a; make the
507 reference weak so static programs can still link. This declaration
508 cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP)
509 because rtld.c contains the common defn for _dl_rtld_map, which is
510 incompatible with a weak decl in the same file. */
511 weak_extern (_dl_rtld_map);
512 #endif
514 /* We cannot use a switch here because we cannot locate the switch
515 jump table until we've self-relocated. */
517 #if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
518 if (__builtin_expect (r_type == R_ALPHA_RELATIVE, 0))
520 # if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
521 /* Already done in dynamic linker. */
522 if (map != &GL(dl_rtld_map))
523 # endif
525 /* XXX Make some timings. Maybe it's preverable to test for
526 unaligned access and only do it the complex way if necessary. */
527 void *reloc_addr_1 = reloc_addr;
528 Elf64_Addr reloc_addr_val;
530 /* Load value without causing unaligned trap. */
531 memcpy (&reloc_addr_val, reloc_addr_1, 8);
532 reloc_addr_val += map->l_addr;
534 /* Store value without causing unaligned trap. */
535 memcpy (reloc_addr_1, &reloc_addr_val, 8);
538 # ifndef RTLD_BOOTSTRAP
539 else if (__builtin_expect (r_type == R_ALPHA_NONE, 0))
540 return;
541 # endif
542 else
543 #endif
545 Elf64_Addr loadbase, sym_value;
547 loadbase = RESOLVE (&sym, version, r_type);
548 sym_value = sym ? loadbase + sym->st_value : 0;
549 sym_value += reloc->r_addend;
551 if (r_type == R_ALPHA_GLOB_DAT)
552 *reloc_addr = sym_value;
553 #ifdef RESOLVE_CONFLICT_FIND_MAP
554 /* In .gnu.conflict section, R_ALPHA_JMP_SLOT relocations have
555 R_ALPHA_JMP_SLOT in lower 8 bits and the remaining 24 bits
556 are .rela.plt index. */
557 else if ((r_type & 0xff) == R_ALPHA_JMP_SLOT)
559 /* elf_machine_fixup_plt needs the map reloc_addr points into,
560 while in _dl_resolve_conflicts map is _dl_loaded. */
561 RESOLVE_CONFLICT_FIND_MAP (map, reloc_addr);
562 reloc = ((const Elf64_Rela *) D_PTR (map, l_info[DT_JMPREL]))
563 + (r_type >> 8);
564 elf_machine_fixup_plt (map, 0, reloc, reloc_addr, sym_value);
566 #else
567 else if (r_type == R_ALPHA_JMP_SLOT)
568 elf_machine_fixup_plt (map, 0, reloc, reloc_addr, sym_value);
569 #endif
570 #ifndef RTLD_BOOTSTRAP
571 else if (r_type == R_ALPHA_REFQUAD)
573 void *reloc_addr_1 = reloc_addr;
575 /* Store value without causing unaligned trap. */
576 memcpy (reloc_addr_1, &sym_value, 8);
578 #endif
579 else
580 _dl_reloc_bad_type (map, r_type, 0);
584 /* Let do-rel.h know that on Alpha if l_addr is 0, all RELATIVE relocs
585 can be skipped. */
586 #define ELF_MACHINE_REL_RELATIVE 1
588 static inline void
589 elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
590 Elf64_Addr *const reloc_addr)
592 /* XXX Make some timings. Maybe it's preverable to test for
593 unaligned access and only do it the complex way if necessary. */
594 void *reloc_addr_1 = reloc_addr;
595 Elf64_Addr reloc_addr_val;
597 /* Load value without causing unaligned trap. */
598 memcpy (&reloc_addr_val, reloc_addr_1, 8);
599 reloc_addr_val += l_addr;
601 /* Store value without causing unaligned trap. */
602 memcpy (reloc_addr_1, &reloc_addr_val, 8);
605 static inline void
606 elf_machine_lazy_rel (struct link_map *map,
607 Elf64_Addr l_addr, const Elf64_Rela *reloc)
609 Elf64_Addr * const reloc_addr = (void *)(l_addr + reloc->r_offset);
610 unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
612 if (r_type == R_ALPHA_JMP_SLOT)
614 /* Perform a RELATIVE reloc on the .got entry that transfers
615 to the .plt. */
616 *reloc_addr += l_addr;
618 else if (r_type == R_ALPHA_NONE)
619 return;
620 else
621 _dl_reloc_bad_type (map, r_type, 1);
624 #endif /* RESOLVE */