1 /* Make dynamic PLABELs for function pointers. HPPA version.
2 Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 #include <sys/param.h>
27 #include <elf/dynamic-link.h>
28 #include <dl-machine.h>
29 #ifdef _LIBC_REENTRANT
30 # include <pt-machine.h>
32 /* Remember, we use 0 to mean that a lock is taken on PA-RISC. */
33 static int __hppa_fptr_lock
= 1;
36 /* Because ld.so is now versioned, these functions can be in their own
37 file; no relocations need to be done to call them. Of course, if
38 ld.so is not versioned... */
41 # error "This will not work with versioning turned off, sorry."
46 /* The fd is not examined when using MAP_ANON. */
49 # define ANONFD GL(dl_zerofd)
52 struct hppa_fptr __boot_ldso_fptr
[HPPA_BOOT_FPTR_SIZE
];
53 struct hppa_fptr
*__fptr_root
= NULL
;
54 struct hppa_fptr
*__fptr_next
= __boot_ldso_fptr
;
55 static struct hppa_fptr
*__fptr_free
= NULL
;
56 int __fptr_count
= HPPA_BOOT_FPTR_SIZE
;
59 __hppa_make_fptr (const struct link_map
*sym_map
, Elf32_Addr value
,
60 struct hppa_fptr
**root
, struct hppa_fptr
*mem
)
62 struct hppa_fptr
**loc
;
65 #ifdef _LIBC_REENTRANT
66 /* Make sure we are alone. We don't need a lock during bootstrap. */
68 while (testandset (&__hppa_fptr_lock
));
71 /* Search the sorted linked list for an existing entry for this
75 while (f
!= NULL
&& f
->func
<= value
)
83 /* Not found. Create a new one. */
86 else if (__fptr_free
!= NULL
)
89 __fptr_free
= f
->next
;
93 if (__fptr_count
== 0)
97 if (GL(dl_zerofd
) == -1)
99 GL(dl_zerofd
) = _dl_sysdep_open_zero_fill ();
100 if (GL(dl_zerofd
) == -1)
103 _dl_signal_error (errno
, NULL
, NULL
,
104 "cannot open zero fill device");
109 __fptr_next
= __mmap (0, GL(dl_pagesize
), PROT_READ
| PROT_WRITE
,
110 MAP_ANON
| MAP_PRIVATE
, ANONFD
, 0);
111 if (__fptr_next
== MAP_FAILED
)
112 _dl_signal_error(errno
, NULL
, NULL
, "cannot map page for fptr");
113 __fptr_count
= GL(dl_pagesize
) / sizeof (struct hppa_fptr
);
120 /* GOT has already been relocated in elf_get_dynamic_info - don't
121 try to relocate it again. */
122 f
->gp
= sym_map
->l_info
[DT_PLTGOT
]->d_un
.d_ptr
;
127 #ifdef _LIBC_REENTRANT
128 /* Release the lock. Again, remember, zero means the lock is taken! */
130 __hppa_fptr_lock
= 1;
133 /* Set bit 30 to indicate to $$dyncall that this is a PLABEL. */
134 return (Elf32_Addr
) f
| 2;
138 _dl_unmap (struct link_map
*map
)
140 struct hppa_fptr
**floc
;
142 struct hppa_fptr
**lloc
;
145 __munmap ((void *) map
->l_map_start
, map
->l_map_end
- map
->l_map_start
);
147 #ifdef _LIBC_REENTRANT
148 /* Make sure we are alone. */
149 while (testandset (&__hppa_fptr_lock
));
152 /* Search the sorted linked list for the first entry for this object. */
155 while (f
!= NULL
&& f
->func
< map
->l_map_start
)
162 if (f
!= NULL
&& f
->func
< map
->l_map_end
)
164 /* Get the last entry. */
167 while (l
&& l
->func
< map
->l_map_end
)
176 /* Prepend them to the free list. */
181 #ifdef _LIBC_REENTRANT
182 /* Release the lock. */
183 __hppa_fptr_lock
= 1;
188 _dl_lookup_address (const void *address
)
190 Elf32_Addr addr
= (Elf32_Addr
) address
;
193 #ifdef _LIBC_REENTRANT
194 /* Make sure we are alone. */
195 while (testandset (&__hppa_fptr_lock
));
198 for (f
= __fptr_root
; f
!= NULL
; f
= f
->next
)
205 #ifdef _LIBC_REENTRANT
206 /* Release the lock. */
207 __hppa_fptr_lock
= 1;