* elf/dynamic-link.h (elf_machine_rel, elf_machine_rela,
[glibc.git] / sysdeps / hppa / dl-machine.h
blobcd180e7f7641b39ecb0b5c039aaf1b2ad0dd2460
1 /* Machine-dependent ELF dynamic relocation inline functions. PA-RISC version.
2 Copyright (C) 1995-1997,1999,2000,2001,2002, 2003
3 Free Software Foundation, Inc.
4 Contributed by David Huggins-Daines <dhd@debian.org>
5 This file is part of the GNU C Library.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library 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 GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA. */
22 #ifndef dl_machine_h
23 #define dl_machine_h 1
25 #define ELF_MACHINE_NAME "hppa"
27 #include <sys/param.h>
28 #include <string.h>
29 #include <link.h>
30 #include <assert.h>
32 /* These must match the definition of the stub in bfd/elf32-hppa.c. */
33 #define SIZEOF_PLT_STUB (4*4)
34 #define GOT_FROM_PLT_STUB (4*4)
36 /* A PLABEL is a function descriptor. Properly they consist of just
37 FUNC and GP. But we want to traverse a binary tree too. See
38 dl-fptr.c for the code (it may be made common between HPPA and
39 IA-64 in the future).
41 We call these 'fptr' to make it easier to steal code from IA-64. */
43 /* ld.so currently has 12 PLABEL32 relocs. We'll keep this constant
44 large for now in case we require more, as the rest of these will be
45 used by the dynamic program itself (libc.so has quite a few
46 PLABEL32 relocs in it). */
47 #define HPPA_BOOT_FPTR_SIZE 256
49 struct hppa_fptr
51 Elf32_Addr func;
52 Elf32_Addr gp;
53 struct hppa_fptr *next;
56 extern struct hppa_fptr __boot_ldso_fptr[];
57 extern struct hppa_fptr *__fptr_root;
58 extern int __fptr_count;
60 extern Elf32_Addr __hppa_make_fptr (const struct link_map *, Elf32_Addr,
61 struct hppa_fptr **, struct hppa_fptr *);
63 /* Return nonzero iff ELF header is compatible with the running host. */
64 static inline int
65 elf_machine_matches_host (const Elf32_Ehdr *ehdr)
67 return ehdr->e_machine == EM_PARISC;
71 /* Return the link-time address of _DYNAMIC. */
72 static inline Elf32_Addr
73 elf_machine_dynamic (void)
75 Elf32_Addr dynamic;
77 #if 0
78 /* Use this method if GOT address not yet set up. */
79 asm (
80 " b,l 1f,%0\n"
81 " depi 0,31,2,%0\n"
82 "1: addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 8),%0\n"
83 " ldw R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 12)(%%r1),%0\n"
84 : "=r" (dynamic) : : "r1");
85 #else
86 /* This works because we already have our GOT address available. */
87 dynamic = (Elf32_Addr) &_DYNAMIC;
88 #endif
90 return dynamic;
93 /* Return the run-time load address of the shared object. */
94 static inline Elf32_Addr
95 elf_machine_load_address (void)
97 Elf32_Addr dynamic, dynamic_linkaddress;
99 asm (
100 " b,l 1f,%0\n"
101 " depi 0,31,2,%0\n"
102 "1: addil L'_DYNAMIC - ($PIC_pcrel$0 - 8),%0\n"
103 " ldo R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%%r1),%1\n"
104 " addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16),%0\n"
105 " ldw R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%%r1),%0\n"
106 : "=r" (dynamic_linkaddress), "=r" (dynamic) : : "r1");
108 return dynamic - dynamic_linkaddress;
111 /* Fixup a PLT entry to bounce directly to the function at VALUE. */
112 static inline Elf32_Addr
113 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
114 const Elf32_Rela *reloc,
115 Elf32_Addr *reloc_addr, Elf32_Addr value)
117 /* l is the link_map for the caller, t is the link_map for the object
118 * being called */
119 reloc_addr[1] = D_PTR (t, l_info[DT_PLTGOT]);
120 reloc_addr[0] = value;
121 /* Return the PLT slot rather than the function value so that the
122 trampoline can load the new LTP. */
123 return (Elf32_Addr) reloc_addr;
126 /* Return the final value of a plt relocation. */
127 static inline Elf32_Addr
128 elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
129 Elf32_Addr value)
131 /* We are rela only */
132 return value + reloc->r_addend;
135 /* Set up the loaded object described by L so its unrelocated PLT
136 entries will jump to the on-demand fixup code in dl-runtime.c. */
138 static inline int
139 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
141 extern void _dl_runtime_resolve (void);
142 extern void _dl_runtime_profile (void);
143 Elf32_Addr jmprel = D_PTR(l, l_info[DT_JMPREL]);
145 if (lazy && jmprel)
147 Elf32_Addr *got = NULL;
148 Elf32_Addr l_addr;
149 Elf32_Addr end_jmprel;
150 Elf32_Addr iplt;
152 /* Relocate all the PLT slots. */
153 l_addr = l->l_addr;
154 end_jmprel = jmprel + l->l_info[DT_PLTRELSZ]->d_un.d_val;
155 for (iplt = jmprel; iplt < end_jmprel; iplt += sizeof (Elf32_Rela))
157 const Elf32_Rela *reloc;
158 Elf32_Word r_type;
159 Elf32_Word r_sym;
160 struct hppa_fptr *fptr;
162 reloc = (const Elf32_Rela *) iplt;
163 r_type = ELF32_R_TYPE (reloc->r_info);
164 r_sym = ELF32_R_SYM (reloc->r_info);
166 if (__builtin_expect (r_type == R_PARISC_IPLT, 1))
168 fptr = (struct hppa_fptr *) (reloc->r_offset + l_addr);
169 if (r_sym != 0)
171 /* Relocate the pointer to the stub. */
172 fptr->func += l_addr;
173 /* Instead of the LTP value, we put the reloc offset
174 here. The trampoline code will load the proper
175 LTP and pass the reloc offset to the fixup
176 function. */
177 fptr->gp = iplt - jmprel;
178 if (!got)
180 static union {
181 unsigned char c[8];
182 Elf32_Addr i[2];
183 } sig = {{0x00,0xc0,0xff,0xee, 0xde,0xad,0xbe,0xef}};
185 /* Find our .got section. It's right after the
186 stub. */
187 got = (Elf32_Addr *) (fptr->func + GOT_FROM_PLT_STUB);
189 /* Sanity check to see if the address we are
190 going to check below is within a reasonable
191 approximation of the bounds of the PLT (or,
192 at least, is at an address that won't fault
193 on read). Then check for the magic signature
194 above. */
195 if (fptr->func < (Elf32_Addr) fptr + sizeof(*fptr))
196 return 0;
197 if (fptr->func >
198 ((Elf32_Addr) fptr
199 + SIZEOF_PLT_STUB
200 + ((l->l_info[DT_PLTRELSZ]->d_un.d_val / sizeof (Elf32_Rela))
201 * 8)))
202 return 0;
203 if (got[-2] != sig.i[0] || got[-1] != sig.i[1])
204 return 0; /* No lazy linking for you! */
207 else
209 /* Relocate this *ABS* entry. */
210 fptr->func = reloc->r_addend + l_addr;
211 fptr->gp = D_PTR (l, l_info[DT_PLTGOT]);
214 else if (__builtin_expect (r_type != R_PARISC_NONE, 0))
215 _dl_reloc_bad_type (l, r_type, 1);
218 if (got)
220 register Elf32_Addr ltp __asm__ ("%r19");
221 /* Identify this shared object. */
222 got[1] = (Elf32_Addr) l;
224 /* This function will be called to perform the relocation. */
225 if (__builtin_expect (!profile, 1))
226 got[-2] =
227 (Elf32_Addr) ((struct hppa_fptr *)
228 ((unsigned long) &_dl_runtime_resolve & ~3))->func;
229 else
231 if (_dl_name_match_p (GL(dl_profile), l))
233 /* This is the object we are looking for. Say that
234 we really want profiling and the timers are
235 started. */
236 GL(dl_profile_map) = l;
238 got[-2] =
239 (Elf32_Addr) ((struct hppa_fptr *)
240 ((unsigned long) &_dl_runtime_profile & ~3))->func;
242 got[-1] = ltp;
245 return lazy;
248 /* Initial entry point code for the dynamic linker.
249 The C function `_dl_start' is the real entry point;
250 its return value is the user program's entry point. */
252 #define RTLD_START \
253 /* Set up dp for any non-PIC lib constructors that may be called. */ \
254 static struct link_map * \
255 set_dp (struct link_map *map) \
257 register Elf32_Addr dp asm ("%r27"); \
258 dp = D_PTR (map, l_info[DT_PLTGOT]); \
259 asm volatile ("" : : "r" (dp)); \
260 return map; \
263 asm ( \
264 " .text\n" \
265 " .globl _start\n" \
266 " .type _start,@function\n" \
267 "_start:\n" \
268 /* The kernel does not give us an initial stack frame. */ \
269 " ldo 64(%sp),%sp\n" \
270 /* Save the relevant arguments (yes, those are the correct \
271 registers, the kernel is weird) in their stack slots. */ \
272 " stw %r25,-40(%sp)\n" /* argc */ \
273 " stw %r24,-44(%sp)\n" /* argv */ \
275 /* We need the LTP, and we need it now. */ \
276 /* $PIC_pcrel$0 points 8 bytes past the current instruction, \
277 just like a branch reloc. This sequence gets us the runtime \
278 address of _DYNAMIC. */ \
279 " bl 0f,%r19\n" \
280 " depi 0,31,2,%r19\n" /* clear priviledge bits */ \
281 "0: addil L'_DYNAMIC - ($PIC_pcrel$0 - 8),%r19\n" \
282 " ldo R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%r26\n" \
284 /* Also get the link time address from the first entry of the GOT. */ \
285 " addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16),%r19\n" \
286 " ldw R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r20\n" \
288 " sub %r26,%r20,%r20\n" /* Calculate load offset */ \
290 /* Rummage through the dynamic entries, looking for DT_PLTGOT. */ \
291 " ldw,ma 8(%r26),%r19\n" \
292 "1: cmpib,=,n 3,%r19,2f\n" /* tag == DT_PLTGOT? */ \
293 " cmpib,<>,n 0,%r19,1b\n" \
294 " ldw,ma 8(%r26),%r19\n" \
296 /* Uh oh! We didn't find one. Abort. */ \
297 " iitlbp %r0,(%r0)\n" \
299 "2: ldw -4(%r26),%r19\n" /* Found it, load value. */ \
300 " add %r19,%r20,%r19\n" /* And add the load offset. */ \
302 /* Our initial stack layout is rather different from everyone \
303 else's due to the unique PA-RISC ABI. As far as I know it \
304 looks like this: \
306 ----------------------------------- (this frame created above) \
307 | 32 bytes of magic | \
308 |---------------------------------| \
309 | 32 bytes argument/sp save area | \
310 |---------------------------------| ((current->mm->env_end) + 63 & ~63) \
311 | N bytes of slack | \
312 |---------------------------------| \
313 | envvar and arg strings | \
314 |---------------------------------| \
315 | ELF auxiliary info | \
316 | (up to 28 words) | \
317 |---------------------------------| \
318 | Environment variable pointers | \
319 | upwards to NULL | \
320 |---------------------------------| \
321 | Argument pointers | \
322 | upwards to NULL | \
323 |---------------------------------| \
324 | argc (1 word) | \
325 ----------------------------------- \
327 So, obviously, we can't just pass %sp to _dl_start. That's \
328 okay, argv-4 will do just fine. \
330 The pleasant part of this is that if we need to skip \
331 arguments we can just decrement argc and move argv, because \
332 the stack pointer is utterly unrelated to the location of \
333 the environment and argument vectors. */ \
335 /* This is always within range so we'll be okay. */ \
336 " bl _dl_start,%rp\n" \
337 " ldo -4(%r24),%r26\n" \
339 " .globl _dl_start_user\n" \
340 " .type _dl_start_user,@function\n" \
341 "_dl_start_user:\n" \
342 /* Save the entry point in %r3. */ \
343 " copy %ret0,%r3\n" \
345 /* Remember the lowest stack address. */ \
346 " addil LT'__libc_stack_end,%r19\n" \
347 " ldw RT'__libc_stack_end(%r1),%r20\n" \
348 " stw %sp,0(%r20)\n" \
350 /* See if we were called as a command with the executable file \
351 name as an extra leading argument. */ \
352 " addil LT'_dl_skip_args,%r19\n" \
353 " ldw RT'_dl_skip_args(%r1),%r20\n" \
354 " ldw 0(%r20),%r20\n" \
356 " ldw -40(%sp),%r25\n" /* argc */ \
357 " comib,= 0,%r20,.Lnofix\n" /* FIXME: will be mispredicted */ \
358 " ldw -44(%sp),%r24\n" /* argv (delay slot) */ \
360 " sub %r25,%r20,%r25\n" \
361 " stw %r25,-40(%sp)\n" \
362 " sh2add %r20,%r24,%r24\n" \
363 " stw %r24,-44(%sp)\n" \
365 ".Lnofix:\n" \
366 " addil LT'_rtld_local,%r19\n" \
367 " ldw RT'_rtld_local(%r1),%r26\n" \
368 " bl set_dp, %r2\n" \
369 " ldw 0(%r26),%r26\n" \
371 /* Call _dl_init(_dl_loaded, argc, argv, envp). */ \
372 " copy %r28,%r26\n" \
374 /* envp = argv + argc + 1 */ \
375 " sh2add %r25,%r24,%r23\n" \
376 " bl _dl_init_internal,%r2\n" \
377 " ldo 4(%r23),%r23\n" /* delay slot */ \
379 /* Reload argc, argv to the registers start.S expects them in (feh) */ \
380 " ldw -40(%sp),%r25\n" \
381 " ldw -44(%sp),%r24\n" \
383 /* _dl_fini does have a PLT slot now. I don't know how to get \
384 to it though, so this hack will remain. */ \
385 " .section .data\n" \
386 "__dl_fini_plabel:\n" \
387 " .word _dl_fini\n" \
388 " .word 0xdeadbeef\n" \
389 " .previous\n" \
391 /* %r3 contains a function pointer, we need to mask out the lower \
392 * bits and load the gp and jump address. */ \
393 " depi 0,31,2,%r3\n" \
394 " ldw 0(%r3),%r2\n" \
395 " addil LT'__dl_fini_plabel,%r19\n" \
396 " ldw RT'__dl_fini_plabel(%r1),%r23\n" \
397 " stw %r19,4(%r23)\n" \
398 " ldw 4(%r3),%r19\n" /* load the object's gp */ \
399 " bv %r0(%r2)\n" \
400 " depi 2,31,2,%r23\n" /* delay slot */ \
404 /* This code gets called via the .plt stub, and is used in
405 dl-runtime.c to call the `fixup' function and then redirect to the
406 address it returns.
407 Enter with r19 = reloc offset, r20 = got-8, r21 = fixup ltp. */
408 #define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
409 extern void tramp_name (void); \
410 asm ( "\
411 /* Trampoline for " #tramp_name " */ \n\
412 .globl " #tramp_name " \n\
413 .type " #tramp_name ",@function \n\
414 " #tramp_name ": \n\
415 /* Save return pointer */ \n\
416 stw %r2,-20(%sp) \n\
417 /* Save argument registers in the call stack frame. */ \n\
418 stw %r26,-36(%sp) \n\
419 stw %r25,-40(%sp) \n\
420 stw %r24,-44(%sp) \n\
421 stw %r23,-48(%sp) \n\
422 /* Build a call frame. */ \n\
423 stwm %sp,64(%sp) \n\
425 /* Set up args to fixup func. */ \n\
426 ldw 8+4(%r20),%r26 /* got[1] == struct link_map * */ \n\
427 copy %r19,%r25 /* reloc offset */ \n\
429 /* Call the real address resolver. */ \n\
430 bl " #fixup_name ",%r2 \n\
431 copy %r21,%r19 /* delay slot, set fixup func ltp */ \n\
433 ldwm -64(%sp),%sp \n\
434 /* Arguments. */ \n\
435 ldw -36(%sp),%r26 \n\
436 ldw -40(%sp),%r25 \n\
437 ldw -44(%sp),%r24 \n\
438 ldw -48(%sp),%r23 \n\
439 /* Return pointer. */ \n\
440 ldw -20(%sp),%r2 \n\
441 /* Call the real function. */ \n\
442 ldw 0(%r28),%r22 \n\
443 bv %r0(%r22) \n\
444 ldw 4(%r28),%r19 \n\
447 #ifndef PROF
448 #define ELF_MACHINE_RUNTIME_TRAMPOLINE \
449 TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
450 TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
451 #else
452 #define ELF_MACHINE_RUNTIME_TRAMPOLINE \
453 TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup); \
454 strong_alias (_dl_runtime_resolve, _dl_runtime_profile);
455 #endif
458 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
459 PLT entries should not be allowed to define the value.
460 ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
461 of the main executable's symbols, as for a COPY reloc. */
462 #define elf_machine_type_class(type) \
463 ((((type) == R_PARISC_IPLT || (type) == R_PARISC_EPLT) \
464 * ELF_RTYPE_CLASS_PLT) \
465 | (((type) == R_PARISC_COPY) * ELF_RTYPE_CLASS_COPY))
467 /* Used by ld.so for ... something ... */
468 #define ELF_MACHINE_JMP_SLOT R_PARISC_IPLT
470 /* We only use RELA. */
471 #define ELF_MACHINE_NO_REL 1
473 /* Return the address of the entry point. */
474 #define ELF_MACHINE_START_ADDRESS(map, start) \
475 DL_FUNCTION_ADDRESS (map, start)
477 #endif /* !dl_machine_h */
479 /* These are only actually used where RESOLVE_MAP is defined, anyway. */
480 #ifdef RESOLVE_MAP
482 static inline void
483 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
484 const Elf32_Sym *sym, const struct r_found_version *version,
485 void *const reloc_addr_arg)
487 Elf32_Addr *const reloc_addr = reloc_addr_arg;
488 const Elf32_Sym *const refsym = sym;
489 unsigned long const r_type = ELF32_R_TYPE (reloc->r_info);
490 struct link_map *sym_map;
491 Elf32_Addr value;
493 #if !defined RTLD_BOOTSTRAP && !defined SHARED
494 /* This is defined in rtld.c, but nowhere in the static libc.a; make the
495 reference weak so static programs can still link. This declaration
496 cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP)
497 because rtld.c contains the common defn for _dl_rtld_map, which is
498 incompatible with a weak decl in the same file. */
499 weak_extern (GL(dl_rtld_map));
500 #endif
502 /* RESOLVE_MAP will return a null value for undefined syms, and
503 non-null for all other syms. In particular, relocs with no
504 symbol (symbol index of zero), also called *ABS* relocs, will be
505 resolved to MAP. (The first entry in a symbol table is all
506 zeros, and an all zero Elf32_Sym has a binding of STB_LOCAL.)
507 See RESOLVE_MAP definition in elf/dl-reloc.c */
508 #ifdef RTLD_BOOTSTRAP
509 /* RESOLVE_MAP in rtld.c doesn't have the local sym test. */
510 sym_map = (ELF32_ST_BIND (sym->st_info) != STB_LOCAL
511 ? RESOLVE_MAP (&sym, version, r_type) : map);
512 #else
513 sym_map = RESOLVE_MAP (&sym, version, r_type);
514 #endif
515 if (sym_map)
517 value = sym ? sym_map->l_addr + sym->st_value : 0;
518 value += reloc->r_addend;
520 else
521 value = 0;
523 switch (r_type)
525 case R_PARISC_DIR32:
526 #ifndef RTLD_BOOTSTRAP
527 /* All hell breaks loose if we try to relocate these twice,
528 because any initialized variables in ld.so that refer to
529 other ones will have their values reset. In particular,
530 __fptr_next will be reset, sometimes causing endless loops in
531 __hppa_make_fptr(). So don't do that. */
532 if (map == &GL(dl_rtld_map))
533 return;
534 #endif
535 /* .eh_frame can have unaligned relocs. */
536 if ((unsigned long) reloc_addr_arg & 3)
538 char *rel_addr = (char *) reloc_addr_arg;
539 rel_addr[0] = value >> 24;
540 rel_addr[1] = value >> 16;
541 rel_addr[2] = value >> 8;
542 rel_addr[3] = value;
543 return;
545 break;
547 case R_PARISC_PLABEL32:
548 /* Easy rule: If there is a symbol and it is global, then we
549 need to make a dynamic function descriptor. Otherwise we
550 have the address of a PLT slot for a local symbol which we
551 know to be unique. */
552 if (sym == NULL
553 || sym_map == NULL
554 || ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
555 break;
557 /* Okay, we need to make ourselves a PLABEL then. See the IA64
558 code for an explanation of how this works. */
559 #ifndef RTLD_BOOTSTRAP
560 value = __hppa_make_fptr (sym_map, value, &__fptr_root, NULL);
561 #else
563 struct hppa_fptr *p_boot_ldso_fptr;
564 struct hppa_fptr **p_fptr_root;
565 int *p_fptr_count;
566 unsigned long dot;
568 /* Go from the top of __boot_ldso_fptr. As on IA64, we
569 probably haven't relocated the necessary values by this
570 point so we have to find them ourselves. */
572 asm ("bl 0f,%0 \n\
573 depi 0,31,2,%0 \n\
574 0: addil L'__boot_ldso_fptr - ($PIC_pcrel$0 - 8),%0 \n\
575 ldo R'__boot_ldso_fptr - ($PIC_pcrel$0 - 12)(%%r1),%1 \n\
576 addil L'__fptr_root - ($PIC_pcrel$0 - 16),%0 \n\
577 ldo R'__fptr_root - ($PIC_pcrel$0 - 20)(%%r1),%2 \n\
578 addil L'__fptr_count - ($PIC_pcrel$0 - 24),%0 \n\
579 ldo R'__fptr_count - ($PIC_pcrel$0 - 28)(%%r1),%3"
581 "=r" (dot),
582 "=r" (p_boot_ldso_fptr),
583 "=r" (p_fptr_root),
584 "=r" (p_fptr_count));
586 value = __hppa_make_fptr (sym_map, value, p_fptr_root,
587 &p_boot_ldso_fptr[--*p_fptr_count]);
589 #endif
590 break;
592 case R_PARISC_IPLT:
593 if (__builtin_expect (sym_map != NULL, 1))
594 elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr, value);
595 else
597 /* If we get here, it's a (weak) undefined sym. */
598 elf_machine_fixup_plt (NULL, map, reloc, reloc_addr, value);
600 return;
602 case R_PARISC_COPY:
603 if (__builtin_expect (sym == NULL, 0))
604 /* This can happen in trace mode if an object could not be
605 found. */
606 break;
607 if (__builtin_expect (sym->st_size > refsym->st_size, 0)
608 || (__builtin_expect (sym->st_size < refsym->st_size, 0)
609 && __builtin_expect (GL(dl_verbose), 0)))
611 const char *strtab;
613 strtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
614 _dl_error_printf ("\
615 %s: Symbol `%s' has different size in shared object, consider re-linking\n",
616 rtld_progname ?: "<program name unknown>",
617 strtab + refsym->st_name);
619 memcpy (reloc_addr_arg, (void *) value,
620 MIN (sym->st_size, refsym->st_size));
621 return;
623 case R_PARISC_NONE: /* Alright, Wilbur. */
624 return;
626 default:
627 _dl_reloc_bad_type (map, r_type, 0);
630 *reloc_addr = value;
633 #define DO_ELF_MACHINE_REL_RELATIVE(map, l_addr, relative) \
634 elf_machine_rel_relative (map, l_addr, relative, \
635 (void *) (l_addr + relative->r_offset))
637 /* hppa doesn't have an R_PARISC_RELATIVE reloc, but uses relocs with
638 ELF32_R_SYM (info) == 0 for a similar purpose. */
639 static inline void
640 elf_machine_rela_relative (struct link_map *map, Elf32_Addr l_addr,
641 const Elf32_Rela *reloc,
642 void *const reloc_addr_arg)
644 Elf32_Addr *const reloc_addr = reloc_addr_arg;
645 unsigned long const r_type = ELF32_R_TYPE (reloc->r_info);
646 Elf32_Addr value;
648 value = l_addr + reloc->r_addend;
650 if (ELF32_R_SYM (reloc->r_info) != 0)
651 asm volatile ("iitlbp %r0,(%r0)"); /* Crash. */
653 switch (r_type)
655 case R_PARISC_DIR32:
656 /* .eh_frame can have unaligned relocs. */
657 if ((unsigned long) reloc_addr_arg & 3)
659 char *rel_addr = (char *) reloc_addr_arg;
660 rel_addr[0] = value >> 24;
661 rel_addr[1] = value >> 16;
662 rel_addr[2] = value >> 8;
663 rel_addr[3] = value;
664 return;
666 break;
668 case R_PARISC_PLABEL32:
669 break;
671 case R_PARISC_IPLT:
672 elf_machine_fixup_plt (NULL, map, reloc, reloc_addr, value);
673 return;
675 case R_PARISC_NONE:
676 return;
678 default:
679 _dl_reloc_bad_type (map, r_type, 0);
682 *reloc_addr = value;
685 static inline void
686 elf_machine_lazy_rel (struct link_map *map,
687 Elf32_Addr l_addr, const Elf32_Rela *reloc)
689 /* We don't have anything to do here. elf_machine_runtime_setup has
690 done all the relocs already. */
693 #endif /* RESOLVE_MAP */