Define F_DUPFD_CLOEXEC.
[glibc-ports.git] / sysdeps / hppa / dl-machine.h
blob08542951c49a4c4b9e1c4c2fb60521e01ba5317f
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
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 <assert.h>
29 #include <string.h>
30 #include <link.h>
31 #include <errno.h>
32 #include <dl-fptr.h>
33 #include <abort-instr.h>
34 #include <tls.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 */
61 static inline void
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. */
77 static inline int
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)
90 Elf32_Addr dynamic;
92 asm ("b,l 1f,%0\n"
93 " depi 0,31,2,%0\n"
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");
98 return dynamic;
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)
108 Elf32_Addr dynamic;
110 asm (
111 " b,l 1f,%0\n"
112 " depi 0,31,2,%0\n"
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
128 being called */
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;
133 return value;
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,
139 struct fdesc value)
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. */
148 static inline int
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;
154 struct fdesc *fptr;
155 static union {
156 unsigned char c[8];
157 Elf32_Addr i[2];
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))
162 return lazy;
164 /* All paths use these values */
165 l_addr = l->l_addr;
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);
172 /* Linking lazily */
173 if (lazy)
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);
192 continue;
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 */
201 else
203 /* Found the GOT! */
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;
219 else
221 /* Static executable! */
222 got[-2] = (Elf32_Addr) &_dl_runtime_resolve;
225 else
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
232 started. */
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;
241 else
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 */
249 got[-1] = ltp;
250 break;
251 /* Done looking for the GOT, and stub is setup */
252 } /* else we found the GOT */
253 } /* for, walk the relocs backwards */
255 if(!got)
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);
268 if (r_sym != 0)
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
276 function. */
277 fptr->gp = iplt - jmprel;
278 } /* r_sym != 0 */
279 else
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 */
287 } /* if lazy */
288 else
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 */
305 return lazy;
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. */
317 #define RTLD_START \
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)); \
325 return map; \
328 asm ( \
329 " .text\n" \
330 " .globl _start\n" \
331 " .type _start,@function\n" \
332 "_start:\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. */ \
344 " bl 0f,%r19\n" \
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 \
350 GOT. */ \
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 \
357 DT_PLTGOT. */ \
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 \
371 looks like this: \
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 |---------------------------------| \
391 | argc (1 word) | \
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" \
432 ".Lnofix:\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" \
458 " .previous\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 */ \
468 " bv %r0(%r2)\n" \
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))
485 #else
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))
491 #endif
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. */
519 #ifdef RESOLVE_MAP
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;
543 Elf32_Addr value;
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));
552 # endif
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);
564 # else
565 sym_map = RESOLVE_MAP (&sym, version, r_type);
566 # endif
568 if (sym_map)
570 value = sym ? sym_map->l_addr + sym->st_value : 0;
571 value += reloc->r_addend;
573 else
574 value = 0;
576 switch (r_type)
578 case R_PARISC_DIR32:
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;
586 rel_addr[3] = value;
587 return;
589 break;
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);
596 value = value >> 11;
597 insn = (insn &~ 0x1fffff) | reassemble_21 (value);
598 *(unsigned int *)reloc_addr = insn;
600 return;
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;
610 return;
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. */
617 if (sym == NULL
618 || sym_map == NULL
619 || ELF32_ST_BIND (sym->st_info) == STB_LOCAL)
621 break;
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
626 protection bits */
627 value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
628 break;
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))
636 break;
638 value = (Elf32_Addr)((unsigned int)_dl_make_fptr (sym_map, sym, value) | 2);
640 if (r_type == R_PARISC_PLABEL21L)
642 value >>= 11;
643 insn = (insn &~ 0x1fffff) | reassemble_21 (value);
645 else
647 value &= 0x7ff;
648 insn = (insn &~ 0x3fff) | reassemble_14 (value);
651 *(unsigned int *)reloc_addr = insn;
653 return;
655 case R_PARISC_IPLT:
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));
661 else
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));
667 return;
669 case R_PARISC_COPY:
670 if (__builtin_expect (sym == NULL, 0))
671 /* This can happen in trace mode if an object could not be
672 found. */
673 break;
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)))
678 const char *strtab;
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));
688 return;
690 #if defined USE_TLS && (!defined RTLD_BOOTSTRAP)
691 case R_PARISC_TLS_DTPMOD32:
692 value = sym_map->l_tls_modid;
693 break;
695 case R_PARISC_TLS_DTPOFF32:
696 /* During relocation all TLS symbols are defined and used.
697 Therefore the offset is already correct. */
698 if (sym != NULL)
699 *reloc_addr = sym->st_value;
700 return;
702 case R_PARISC_TLS_TPREL32:
703 /* The offset is negative, forward from the thread pointer */
704 if (sym != NULL)
706 CHECK_STATIC_TLS (map, sym_map);
707 value = sym_map->l_tls_offset + sym->st_value + reloc->r_addend;
709 break;
710 #endif /* use TLS */
712 case R_PARISC_NONE: /* Alright, Wilbur. */
713 return;
715 default:
716 _dl_reloc_bad_type (map, r_type, 0);
719 *reloc_addr = value;
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" };
732 struct link_map map;
733 Elf32_Addr value;
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. */
744 switch (r_type)
746 case R_PARISC_DIR32:
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;
754 rel_addr[3] = value;
755 return;
757 break;
759 case R_PARISC_PLABEL32:
760 break;
762 case R_PARISC_IPLT: /* elf_machine_runtime_setup already set gp */
763 break;
765 case R_PARISC_NONE:
766 return;
768 default: /* Bad reloc, map unknown (really it's the current map) */
769 map.l_name = msgbuf;
770 _dl_reloc_bad_type (&map, r_type, 0);
771 return;
774 *reloc_addr = value;
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 */