1 /* Machine-dependent ELF dynamic relocation inline functions. PA-RISC version.
2 Copyright (C) 1995-1997,1999-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
23 #define dl_machine_h 1
25 #define ELF_MACHINE_NAME "hppa"
27 #include <sys/param.h>
33 #include <abort-instr.h>
36 # define VALID_ELF_OSABI(osabi) ((osabi == ELFOSABI_SYSV) || (osabi == ELFOSABI_LINUX))
37 # define VALID_ELF_ABIVERSION(ver) (ver == 0)
38 # define VALID_ELF_HEADER(hdr,exp,size) \
39 memcmp (hdr,exp,size-2) == 0 \
40 && VALID_ELF_OSABI (hdr[EI_OSABI]) \
41 && VALID_ELF_ABIVERSION (hdr[EI_ABIVERSION])
43 /* These two definitions must match the definition of the stub in
44 bfd/elf32-hppa.c (see plt_stub[]).
46 a. Define the size of the *entire* stub we place at the end of the PLT
47 table (right up against the GOT).
49 b. Define the number of bytes back from the GOT to the entry point of
50 the PLT stub. You see the PLT stub must be entered in the middle
51 so it can depwi to find it's own address (long jump stub)
53 c. Define the size of a single PLT entry so we can jump over the
54 last entry to get the stub address */
56 #define SIZEOF_PLT_STUB (7*4)
57 #define GOT_FROM_PLT_STUB (4*4)
58 #define PLT_ENTRY_SIZE (2*4)
60 /* Initialize the function descriptor table before relocations */
62 __hppa_init_bootstrap_fdesc_table (struct link_map
*map
)
64 ElfW(Addr
) *boot_table
;
66 /* Careful: this will be called before got has been relocated... */
67 ELF_MACHINE_LOAD_ADDRESS(boot_table
,_dl_boot_fptr_table
);
69 map
->l_mach
.fptr_table_len
= ELF_MACHINE_BOOT_FPTR_TABLE_LEN
;
70 map
->l_mach
.fptr_table
= boot_table
;
73 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info) \
74 __hppa_init_bootstrap_fdesc_table (&bootstrap_map);
76 /* Return nonzero iff ELF header is compatible with the running host. */
78 elf_machine_matches_host (const Elf32_Ehdr
*ehdr
)
80 return ehdr
->e_machine
== EM_PARISC
;
83 /* Return the link-time address of _DYNAMIC. */
84 static inline Elf32_Addr
85 elf_machine_dynamic (void) __attribute__ ((const));
87 static inline Elf32_Addr
88 elf_machine_dynamic (void)
94 "1: addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 8),%0\n"
95 " ldw R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 12)(%%r1),%0\n"
96 : "=r" (dynamic
) : : "r1");
101 /* Return the run-time load address of the shared object. */
102 static inline Elf32_Addr
103 elf_machine_load_address (void) __attribute__ ((const));
105 static inline Elf32_Addr
106 elf_machine_load_address (void)
113 "1: addil L'_DYNAMIC - ($PIC_pcrel$0 - 8),%0\n"
114 " ldo R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%%r1),%0\n"
115 : "=r" (dynamic
) : : "r1");
117 return dynamic
- elf_machine_dynamic ();
120 /* Fixup a PLT entry to bounce directly to the function at VALUE. */
121 static inline struct fdesc
__attribute__ ((always_inline
))
122 elf_machine_fixup_plt (struct link_map
*map
, lookup_t t
,
123 const Elf32_Rela
*reloc
,
124 Elf32_Addr
*reloc_addr
, struct fdesc value
)
126 volatile Elf32_Addr
*rfdesc
= reloc_addr
;
127 /* map is the link_map for the caller, t is the link_map for the object
129 rfdesc
[1] = value
.gp
;
130 /* Need to ensure that the gp is visible before the code
131 entry point is updated */
132 rfdesc
[0] = value
.ip
;
136 /* Return the final value of a plt relocation. */
137 static inline struct fdesc
138 elf_machine_plt_value (struct link_map
*map
, const Elf32_Rela
*reloc
,
141 /* We are rela only, return a function descriptor as a plt entry. */
142 return (struct fdesc
) { value
.ip
+ reloc
->r_addend
, value
.gp
};
145 /* Set up the loaded object described by L so its unrelocated PLT
146 entries will jump to the on-demand fixup code in dl-runtime.c. */
149 elf_machine_runtime_setup (struct link_map
*l
, int lazy
, int profile
)
151 Elf32_Addr
*got
= NULL
;
152 Elf32_Addr l_addr
, iplt
, jmprel
, end_jmprel
, r_type
, r_sym
;
153 const Elf32_Rela
*reloc
;
158 } sig
= {{0x00,0xc0,0xff,0xee, 0xde,0xad,0xbe,0xef}};
160 /* If we don't have a PLT we can just skip all this... */
161 if (__builtin_expect (l
->l_info
[DT_JMPREL
] == NULL
,0))
164 /* All paths use these values */
166 jmprel
= D_PTR(l
, l_info
[DT_JMPREL
]);
167 end_jmprel
= jmprel
+ l
->l_info
[DT_PLTRELSZ
]->d_un
.d_val
;
169 extern void _dl_runtime_resolve (void);
170 extern void _dl_runtime_profile (void);
175 /* FIXME: Search for the got, but backwards through the relocs, technically we should
176 find it on the first try. However, assuming the relocs got out of order the
177 routine is made a bit more robust by searching them all in case of failure. */
178 for (iplt
= (end_jmprel
- sizeof(Elf32_Rela
)); iplt
>= jmprel
; iplt
-= sizeof (Elf32_Rela
))
181 reloc
= (const Elf32_Rela
*) iplt
;
182 r_type
= ELF32_R_TYPE (reloc
->r_info
);
183 r_sym
= ELF32_R_SYM (reloc
->r_info
);
185 got
= (Elf32_Addr
*) (reloc
->r_offset
+ l_addr
+ PLT_ENTRY_SIZE
+ SIZEOF_PLT_STUB
);
187 /* If we aren't an IPLT, and we aren't NONE then it's a bad reloc */
188 if (__builtin_expect (r_type
!= R_PARISC_IPLT
, 0))
190 if (__builtin_expect (r_type
!= R_PARISC_NONE
, 0))
191 _dl_reloc_bad_type (l
, r_type
, 1);
195 /* Check for the plt_stub that binutils placed here for us
196 to use with _dl_runtime_resolve */
197 if (got
[-2] != sig
.i
[0] || got
[-1] != sig
.i
[1])
199 got
= NULL
; /* Not the stub... keep looking */
204 register Elf32_Addr ltp
__asm__ ("%r19");
206 /* Identify this shared object. Second entry in the got. */
207 got
[1] = (Elf32_Addr
) l
;
209 /* This function will be called to perform the relocation. */
210 if (__builtin_expect (!profile
, 1))
212 /* If a static application called us, then _dl_runtime_resolve is not
213 a function descriptor, but the *real* address of the function... */
214 if((unsigned long) &_dl_runtime_resolve
& 3)
216 got
[-2] = (Elf32_Addr
) ((struct fdesc
*)
217 ((unsigned long) &_dl_runtime_resolve
& ~3))->ip
;
221 /* Static executable! */
222 got
[-2] = (Elf32_Addr
) &_dl_runtime_resolve
;
227 if (GLRO(dl_profile
) != NULL
228 && _dl_name_match_p (GLRO(dl_profile
), l
))
230 /* This is the object we are looking for. Say that
231 we really want profiling and the timers are
233 GL(dl_profile_map
) = l
;
236 if((unsigned long) &_dl_runtime_resolve
& 3)
238 got
[-2] = (Elf32_Addr
) ((struct fdesc
*)
239 ((unsigned long) &_dl_runtime_profile
& ~3))->ip
;
243 /* Static executable */
244 got
[-2] = (Elf32_Addr
) &_dl_runtime_profile
;
247 /* Plunk in the gp of this function descriptor so we
248 can make the call to _dl_runtime_xxxxxx */
251 /* Done looking for the GOT, and stub is setup */
252 } /* else we found the GOT */
253 } /* for, walk the relocs backwards */
256 return 0; /* No lazy linking for you! */
258 /* Process all the relocs, now that we know the GOT... */
259 for (iplt
= jmprel
; iplt
< end_jmprel
; iplt
+= sizeof (Elf32_Rela
))
261 reloc
= (const Elf32_Rela
*) iplt
;
262 r_type
= ELF32_R_TYPE (reloc
->r_info
);
263 r_sym
= ELF32_R_SYM (reloc
->r_info
);
265 if (__builtin_expect (r_type
== R_PARISC_IPLT
, 1))
267 fptr
= (struct fdesc
*) (reloc
->r_offset
+ l_addr
);
270 /* Relocate the pointer to the stub. */
271 fptr
->ip
= (Elf32_Addr
) got
- GOT_FROM_PLT_STUB
;
273 /* Instead of the LTP value, we put the reloc offset
274 here. The trampoline code will load the proper
275 LTP and pass the reloc offset to the fixup
277 fptr
->gp
= iplt
- jmprel
;
281 /* Relocate this *ABS* entry. */
282 fptr
->ip
= reloc
->r_addend
+ l_addr
;
283 fptr
->gp
= D_PTR (l
, l_info
[DT_PLTGOT
]);
285 } /* r_type == R_PARISC_IPLT */
286 } /* for all the relocations */
290 for (iplt
= jmprel
; iplt
< end_jmprel
; iplt
+= sizeof (Elf32_Rela
))
292 reloc
= (const Elf32_Rela
*) iplt
;
293 r_type
= ELF32_R_TYPE (reloc
->r_info
);
294 r_sym
= ELF32_R_SYM (reloc
->r_info
);
296 if (__builtin_expect ((r_type
== R_PARISC_IPLT
) && (r_sym
== 0), 1))
298 fptr
= (struct fdesc
*) (reloc
->r_offset
+ l_addr
);
299 /* Relocate this *ABS* entry, set only the gp, the rest is set later
300 when elf_machine_rela_relative is called (WITHOUT the linkmap) */
301 fptr
->gp
= D_PTR (l
, l_info
[DT_PLTGOT
]);
302 } /* r_type == R_PARISC_IPLT */
303 } /* for all the relocations */
309 /* Names of the architecture-specific auditing callback functions. */
310 #define ARCH_LA_PLTENTER hppa_gnu_pltenter
311 #define ARCH_LA_PLTEXIT hppa_gnu_pltexit
313 /* Initial entry point code for the dynamic linker.
314 The C function `_dl_start' is the real entry point;
315 its return value is the user program's entry point. */
318 /* Set up dp for any non-PIC lib constructors that may be called. */ \
319 static struct link_map * __attribute__((used)) \
320 set_dp (struct link_map *map) \
322 register Elf32_Addr dp asm ("%r27"); \
323 dp = D_PTR (map, l_info[DT_PLTGOT]); \
324 asm volatile ("" : : "r" (dp)); \
331 " .type _start,@function\n" \
333 /* The kernel does not give us an initial stack frame. */ \
334 " ldo 64(%sp),%sp\n" \
335 /* Save the relevant arguments (yes, those are the correct \
336 registers, the kernel is weird) in their stack slots. */ \
337 " stw %r25,-40(%sp)\n" /* argc */ \
338 " stw %r24,-44(%sp)\n" /* argv */ \
340 /* We need the LTP, and we need it now. \
341 $PIC_pcrel$0 points 8 bytes past the current instruction, \
342 just like a branch reloc. This sequence gets us the \
343 runtime address of _DYNAMIC. */ \
345 " depi 0,31,2,%r19\n" /* clear priviledge bits */ \
346 "0: addil L'_DYNAMIC - ($PIC_pcrel$0 - 8),%r19\n" \
347 " ldo R'_DYNAMIC - ($PIC_pcrel$0 - 12)(%r1),%r26\n" \
349 /* The link time address is stored in the first entry of the \
351 " addil L'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 16),%r19\n" \
352 " ldw R'_GLOBAL_OFFSET_TABLE_ - ($PIC_pcrel$0 - 20)(%r1),%r20\n" \
354 " sub %r26,%r20,%r20\n" /* Calculate load offset */ \
356 /* Rummage through the dynamic entries, looking for \
358 " ldw,ma 8(%r26),%r19\n" \
359 "1: cmpib,=,n 3,%r19,2f\n" /* tag == DT_PLTGOT? */ \
360 " cmpib,<>,n 0,%r19,1b\n" \
361 " ldw,ma 8(%r26),%r19\n" \
363 /* Uh oh! We didn't find one. Abort. */ \
364 " iitlbp %r0,(%sr0,%r0)\n" \
366 "2: ldw -4(%r26),%r19\n" /* Found it, load value. */ \
367 " add %r19,%r20,%r19\n" /* And add the load offset. */ \
369 /* Our initial stack layout is rather different from everyone \
370 else's due to the unique PA-RISC ABI. As far as I know it \
373 ----------------------------------- (this frame created above) \
374 | 32 bytes of magic | \
375 |---------------------------------| \
376 | 32 bytes argument/sp save area | \
377 |---------------------------------| ((current->mm->env_end) \
378 | N bytes of slack | + 63 & ~63) \
379 |---------------------------------| \
380 | envvar and arg strings | \
381 |---------------------------------| \
382 | ELF auxiliary info | \
383 | (up to 28 words) | \
384 |---------------------------------| \
385 | Environment variable pointers | \
386 | upwards to NULL | \
387 |---------------------------------| \
388 | Argument pointers | \
389 | upwards to NULL | \
390 |---------------------------------| \
392 ----------------------------------- \
394 So, obviously, we can't just pass %sp to _dl_start. That's \
395 okay, argv-4 will do just fine. \
397 The pleasant part of this is that if we need to skip \
398 arguments we can just decrement argc and move argv, because \
399 the stack pointer is utterly unrelated to the location of \
400 the environment and argument vectors. */ \
402 /* This is always within range so we'll be okay. */ \
403 " bl _dl_start,%rp\n" \
404 " ldo -4(%r24),%r26\n" \
406 " .globl _dl_start_user\n" \
407 " .type _dl_start_user,@function\n" \
408 "_dl_start_user:\n" \
409 /* Save the entry point in %r3. */ \
410 " copy %ret0,%r3\n" \
412 /* Remember the lowest stack address. */ \
413 " addil LT'__libc_stack_end,%r19\n" \
414 " ldw RT'__libc_stack_end(%r1),%r20\n" \
415 " stw %sp,0(%r20)\n" \
417 /* See if we were called as a command with the executable file \
418 name as an extra leading argument. */ \
419 " addil LT'_dl_skip_args,%r19\n" \
420 " ldw RT'_dl_skip_args(%r1),%r20\n" \
421 " ldw 0(%r20),%r20\n" \
423 " ldw -40(%sp),%r25\n" /* argc */ \
424 " comib,= 0,%r20,.Lnofix\n" /* FIXME: Mispredicted branch */\
425 " ldw -44(%sp),%r24\n" /* argv (delay slot) */ \
427 " sub %r25,%r20,%r25\n" \
428 " stw %r25,-40(%sp)\n" \
429 " sh2add %r20,%r24,%r24\n" \
430 " stw %r24,-44(%sp)\n" \
433 " addil LT'_rtld_local,%r19\n" \
434 " ldw RT'_rtld_local(%r1),%r26\n" \
435 " bl set_dp, %r2\n" \
436 " ldw 0(%r26),%r26\n" \
438 /* Call _dl_init(_dl_loaded, argc, argv, envp). */ \
439 " copy %r28,%r26\n" \
441 /* envp = argv + argc + 1 */ \
442 " sh2add %r25,%r24,%r23\n" \
443 " bl _dl_init_internal,%r2\n" \
444 " ldo 4(%r23),%r23\n" /* delay slot */ \
446 /* Reload argc, argv to the registers start.S expects. */ \
447 " ldw -40(%sp),%r25\n" \
448 " ldw -44(%sp),%r24\n" \
450 /* _dl_fini is a local function in the loader, so we construct \
451 a false OPD here and pass this to the application. */ \
452 /* FIXME: Should be able to use P%, and LR RR to have the \
453 the linker construct a proper OPD. */ \
454 " .section .data\n" \
455 "__dl_fini_plabel:\n" \
456 " .word _dl_fini\n" \
457 " .word 0xdeadbeef\n" \
460 /* %r3 contains a function pointer, we need to mask out the \
461 lower bits and load the gp and jump address. */ \
462 " depi 0,31,2,%r3\n" \
463 " ldw 0(%r3),%r2\n" \
464 " addil LT'__dl_fini_plabel,%r19\n" \
465 " ldw RT'__dl_fini_plabel(%r1),%r23\n" \
466 " stw %r19,4(%r23)\n" \
467 " ldw 4(%r3),%r19\n" /* load the object's gp */ \
469 " depi 2,31,2,%r23\n" /* delay slot */ \
472 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
473 a TLS variable, so references should not be allowed to define the value.
474 ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
475 of the main executable's symbols, as for a COPY reloc. */
476 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
477 # define elf_machine_type_class(type) \
478 ((((type) == R_PARISC_IPLT \
479 || (type) == R_PARISC_EPLT \
480 || (type) == R_PARISC_TLS_DTPMOD32 \
481 || (type) == R_PARISC_TLS_DTPOFF32 \
482 || (type) == R_PARISC_TLS_TPREL32) \
483 * ELF_RTYPE_CLASS_PLT) \
484 | (((type) == R_PARISC_COPY) * ELF_RTYPE_CLASS_COPY))
486 #define elf_machine_type_class(type) \
487 ((((type) == R_PARISC_IPLT \
488 || (type) == R_PARISC_EPLT) \
489 * ELF_RTYPE_CLASS_PLT) \
490 | (((type) == R_PARISC_COPY) * ELF_RTYPE_CLASS_COPY))
493 /* Used by the runtime in fixup to figure out if reloc is *really* PLT */
494 #define ELF_MACHINE_JMP_SLOT R_PARISC_IPLT
495 #define ELF_MACHINE_SIZEOF_JMP_SLOT PLT_ENTRY_SIZE
497 /* We only use RELA. */
498 #define ELF_MACHINE_NO_REL 1
500 /* Return the address of the entry point. */
501 #define ELF_MACHINE_START_ADDRESS(map, start) \
502 DL_STATIC_FUNCTION_ADDRESS (map, start)
504 /* We define an initialization functions. This is called very early in
505 * _dl_sysdep_start. */
506 #define DL_PLATFORM_INIT dl_platform_init ()
508 static inline void __attribute__ ((unused
))
509 dl_platform_init (void)
511 if (GLRO(dl_platform
) != NULL
&& *GLRO(dl_platform
) == '\0')
512 /* Avoid an empty string which would disturb us. */
513 GLRO(dl_platform
) = NULL
;
516 #endif /* !dl_machine_h */
518 /* These are only actually used where RESOLVE_MAP is defined, anyway. */
521 #define reassemble_21(as21) \
522 ( (((as21) & 0x100000) >> 20) \
523 | (((as21) & 0x0ffe00) >> 8) \
524 | (((as21) & 0x000180) << 7) \
525 | (((as21) & 0x00007c) << 14) \
526 | (((as21) & 0x000003) << 12))
528 #define reassemble_14(as14) \
529 ( (((as14) & 0x1fff) << 1) \
530 | (((as14) & 0x2000) >> 13))
532 auto void __attribute__((always_inline
))
533 elf_machine_rela (struct link_map
*map
,
534 const Elf32_Rela
*reloc
,
535 const Elf32_Sym
*sym
,
536 const struct r_found_version
*version
,
537 void *const reloc_addr_arg
)
539 Elf32_Addr
*const reloc_addr
= reloc_addr_arg
;
540 const Elf32_Sym
*const refsym
= sym
;
541 unsigned long const r_type
= ELF32_R_TYPE (reloc
->r_info
);
542 struct link_map
*sym_map
;
545 # if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC && !defined SHARED
546 /* This is defined in rtld.c, but nowhere in the static libc.a; make the
547 reference weak so static programs can still link. This declaration
548 cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP)
549 because rtld.c contains the common defn for _dl_rtld_map, which is
550 incompatible with a weak decl in the same file. */
551 weak_extern (GL(dl_rtld_map
));
554 /* RESOLVE_MAP will return a null value for undefined syms, and
555 non-null for all other syms. In particular, relocs with no
556 symbol (symbol index of zero), also called *ABS* relocs, will be
557 resolved to MAP. (The first entry in a symbol table is all
558 zeros, and an all zero Elf32_Sym has a binding of STB_LOCAL.)
559 See RESOLVE_MAP definition in elf/dl-reloc.c */
560 # ifdef RTLD_BOOTSTRAP
561 /* RESOLVE_MAP in rtld.c doesn't have the local sym test. */
562 sym_map
= (ELF32_ST_BIND (sym
->st_info
) != STB_LOCAL
563 ? RESOLVE_MAP (&sym
, version
, r_type
) : map
);
565 sym_map
= RESOLVE_MAP (&sym
, version
, r_type
);
570 value
= sym
? sym_map
->l_addr
+ sym
->st_value
: 0;
571 value
+= reloc
->r_addend
;
579 /* .eh_frame can have unaligned relocs. */
580 if ((unsigned long) reloc_addr_arg
& 3)
582 char *rel_addr
= (char *) reloc_addr_arg
;
583 rel_addr
[0] = value
>> 24;
584 rel_addr
[1] = value
>> 16;
585 rel_addr
[2] = value
>> 8;
591 case R_PARISC_DIR21L
:
593 unsigned int insn
= *(unsigned int *)reloc_addr
;
594 value
= sym_map
->l_addr
+ sym
->st_value
595 + ((reloc
->r_addend
+ 0x1000) & -0x2000);
597 insn
= (insn
&~ 0x1fffff) | reassemble_21 (value
);
598 *(unsigned int *)reloc_addr
= insn
;
602 case R_PARISC_DIR14R
:
604 unsigned int insn
= *(unsigned int *)reloc_addr
;
605 value
= ((sym_map
->l_addr
+ sym
->st_value
) & 0x7ff)
606 + (((reloc
->r_addend
& 0x1fff) ^ 0x1000) - 0x1000);
607 insn
= (insn
&~ 0x3fff) | reassemble_14 (value
);
608 *(unsigned int *)reloc_addr
= insn
;
612 case R_PARISC_PLABEL32
:
613 /* Easy rule: If there is a symbol and it is global, then we
614 need to make a dynamic function descriptor. Otherwise we
615 have the address of a PLT slot for a local symbol which we
616 know to be unique. */
619 || ELF32_ST_BIND (sym
->st_info
) == STB_LOCAL
)
623 /* Set bit 30 to indicate to $$dyncall that this is a PLABEL.
624 We have to do this outside of the generic function descriptor
625 code, since it doesn't know about our requirement for setting
627 value
= (Elf32_Addr
)((unsigned int)_dl_make_fptr (sym_map
, sym
, value
) | 2);
630 case R_PARISC_PLABEL21L
:
631 case R_PARISC_PLABEL14R
:
633 unsigned int insn
= *(unsigned int *)reloc_addr
;
635 if (__builtin_expect (sym
== NULL
, 0))
638 value
= (Elf32_Addr
)((unsigned int)_dl_make_fptr (sym_map
, sym
, value
) | 2);
640 if (r_type
== R_PARISC_PLABEL21L
)
643 insn
= (insn
&~ 0x1fffff) | reassemble_21 (value
);
648 insn
= (insn
&~ 0x3fff) | reassemble_14 (value
);
651 *(unsigned int *)reloc_addr
= insn
;
656 if (__builtin_expect (sym_map
!= NULL
, 1))
658 elf_machine_fixup_plt (NULL
, sym_map
, reloc
, reloc_addr
,
659 DL_FIXUP_MAKE_VALUE(sym_map
, value
));
663 /* If we get here, it's a (weak) undefined sym. */
664 elf_machine_fixup_plt (NULL
, map
, reloc
, reloc_addr
,
665 DL_FIXUP_MAKE_VALUE(map
, value
));
670 if (__builtin_expect (sym
== NULL
, 0))
671 /* This can happen in trace mode if an object could not be
674 if (__builtin_expect (sym
->st_size
> refsym
->st_size
, 0)
675 || (__builtin_expect (sym
->st_size
< refsym
->st_size
, 0)
676 && __builtin_expect (GLRO(dl_verbose
), 0)))
680 strtab
= (const char *) D_PTR (map
, l_info
[DT_STRTAB
]);
681 _dl_error_printf ("%s: Symbol `%s' has different size in shared object, "
682 "consider re-linking\n",
683 rtld_progname
?: "<program name unknown>",
684 strtab
+ refsym
->st_name
);
686 memcpy (reloc_addr_arg
, (void *) value
,
687 MIN (sym
->st_size
, refsym
->st_size
));
690 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP)
691 case R_PARISC_TLS_DTPMOD32
:
692 value
= sym_map
->l_tls_modid
;
695 case R_PARISC_TLS_DTPOFF32
:
696 /* During relocation all TLS symbols are defined and used.
697 Therefore the offset is already correct. */
699 *reloc_addr
= sym
->st_value
;
702 case R_PARISC_TLS_TPREL32
:
703 /* The offset is negative, forward from the thread pointer */
706 CHECK_STATIC_TLS (map
, sym_map
);
707 value
= sym_map
->l_tls_offset
+ sym
->st_value
+ reloc
->r_addend
;
712 case R_PARISC_NONE
: /* Alright, Wilbur. */
716 _dl_reloc_bad_type (map
, r_type
, 0);
722 /* hppa doesn't have an R_PARISC_RELATIVE reloc, but uses relocs with
723 ELF32_R_SYM (info) == 0 for a similar purpose. */
724 auto void __attribute__((always_inline
))
725 elf_machine_rela_relative (Elf32_Addr l_addr
,
726 const Elf32_Rela
*reloc
,
727 void *const reloc_addr_arg
)
729 unsigned long const r_type
= ELF32_R_TYPE (reloc
->r_info
);
730 Elf32_Addr
*const reloc_addr
= reloc_addr_arg
;
731 static char msgbuf
[] = { "Unknown" };
735 value
= l_addr
+ reloc
->r_addend
;
737 if (ELF32_R_SYM (reloc
->r_info
) != 0){
738 _dl_error_printf ("%s: In elf_machine_rela_relative "
739 "ELF32_R_SYM (reloc->r_info) != 0. Aborting.",
740 rtld_progname
?: "<program name unknown>");
741 ABORT_INSTRUCTION
; /* Crash. */
747 /* .eh_frame can have unaligned relocs. */
748 if ((unsigned long) reloc_addr_arg
& 3)
750 char *rel_addr
= (char *) reloc_addr_arg
;
751 rel_addr
[0] = value
>> 24;
752 rel_addr
[1] = value
>> 16;
753 rel_addr
[2] = value
>> 8;
759 case R_PARISC_PLABEL32
:
762 case R_PARISC_IPLT
: /* elf_machine_runtime_setup already set gp */
768 default: /* Bad reloc, map unknown (really it's the current map) */
770 _dl_reloc_bad_type (&map
, r_type
, 0);
777 auto void __attribute__((always_inline
))
778 elf_machine_lazy_rel (struct link_map
*map
,
779 Elf32_Addr l_addr
, const Elf32_Rela
*reloc
)
781 /* We don't have anything to do here. elf_machine_runtime_setup has
782 done all the relocs already. */
785 #endif /* RESOLVE_MAP */