aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/ia64
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/ia64')
-rw-r--r--sysdeps/ia64/dl-fptr.c288
1 files changed, 0 insertions, 288 deletions
diff --git a/sysdeps/ia64/dl-fptr.c b/sysdeps/ia64/dl-fptr.c
deleted file mode 100644
index 3c362b0f87..0000000000
--- a/sysdeps/ia64/dl-fptr.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/* Manage function descriptors. IA-64 version.
- Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#include <ia64intrin.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/param.h>
-#include <sys/mman.h>
-#include <link.h>
-#include <ldsodefs.h>
-#include <elf/dynamic-link.h>
-#include <dl-machine.h>
-#ifdef _LIBC_REENTRANT
-# include <ia64intrin.h>
-# include <signal.h>
-# include <time.h>
-#endif
-
-Elf64_Addr __ia64_boot_fptr_table[IA64_BOOT_FPTR_TABLE_LEN];
-
-static struct local
- {
- struct ia64_fdesc_table *root;
- struct ia64_fdesc *free_list;
- unsigned int npages; /* # of pages to allocate */
-#ifdef _LIBC_REENTRANT
- volatile int lock;
- sigset_t full_sigset;
-#endif
- /* the next to members MUST be consecutive! */
- struct ia64_fdesc_table boot_table;
- struct ia64_fdesc boot_fdescs[1024];
- }
-local =
- {
- root: &local.boot_table,
- npages: 2,
- boot_table:
- {
- len: sizeof (local.boot_fdescs) / sizeof (local.boot_fdescs[0]),
- first_unused: 0
- }
- };
-
-/* Locking is tricky: we may get a signal while holding the lock and
- the signal handler may end up calling into the dynamic loader
- again. Also, if a real-time process spins on the lock, a
- non-realtime process may never get the chance to release it's lock,
- unless the realtime process relinquishes the CPU from time to time.
- Hence we (a) block signals before acquiring the lock and (b) do a
- nanosleep() when we detect prolongued contention. */
-#ifdef _LIBC_REENTRANT
-# define lock(l) \
-{ \
- sigset_t _saved_set; \
- int i = 10000; \
- if (!__sigismember (&(l)->full_sigset, SIGINT)) \
- __sigfillset (&(l)->full_sigset); \
- \
- while (__sync_lock_test_and_set (&(l)->lock, 1)) \
- { \
- struct timespec ts; \
- if (i > 0) \
- { \
- --i; \
- continue; \
- } \
- ts.tv_sec = 0; \
- ts.tv_nsec = 1*1000*1000; \
- __nanosleep (&ts, NULL); \
- } \
- __sigprocmask (SIG_BLOCK, &(l)->full_sigset, &_saved_set);
-# define unlock(l) \
- __sigprocmask (SIG_SETMASK, &_saved_set, NULL); \
- __sync_lock_release (&(l)->lock); \
-}
-#else
-# define lock(l)
-# define unlock(l)
-#endif
-
-/* Create a new fdesc table and return a pointer to the first fdesc
- entry. The fdesc lock must have been acquired already. */
-
-static struct ia64_fdesc *
-new_fdesc_table (struct local *l)
-{
- size_t size = l->npages * GL(dl_pagesize);
- struct ia64_fdesc_table *new_table;
- struct ia64_fdesc *fdesc;
-
- l->npages += l->npages;
- new_table = __mmap (0, size, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
- if (new_table == MAP_FAILED)
- _dl_signal_error (errno, NULL, NULL, "cannot map pages for fdesc table");
-
- new_table->len = (size - sizeof (*new_table)) / sizeof (struct ia64_fdesc);
- fdesc = &new_table->fdesc[0];
- new_table->first_unused = 1;
- new_table->next = l->root;
- l->root = new_table;
- return fdesc;
-}
-
-static Elf64_Addr
-make_fdesc (Elf64_Addr ip, Elf64_Addr gp)
-{
- struct ia64_fdesc *fdesc = NULL;
- struct ia64_fdesc_table *t;
- unsigned int old;
- struct local *l;
-
- asm ("movl %0 = @gprel (local);; add %0 = %0, gp" : "=&r"(l));
-
- t = l->root;
- while (1)
- {
- old = t->first_unused;
- if (old >= t->len)
- break;
- else if (__sync_bool_compare_and_swap (&t->first_unused, old, old + 1))
- {
- fdesc = &t->fdesc[old];
- goto install;
- }
- }
-
- lock (l);
- {
- if (l->free_list)
- {
- fdesc = l->free_list; /* get it from free-list */
- l->free_list = (struct ia64_fdesc *) fdesc->ip;
- }
- else
- fdesc = new_fdesc_table (l); /* create new fdesc table */
- }
- unlock (l);
-
- install:
- fdesc->ip = ip;
- fdesc->gp = gp;
-
- return (Elf64_Addr) fdesc;
-}
-
-static inline Elf64_Addr *
-make_fptr_table (struct link_map *map)
-{
- const Elf64_Sym *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
- const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
- Elf64_Addr *fptr_table;
- size_t size;
- size_t len;
-
- /* XXX Apparently the only way to find out the size of the dynamic
- symbol section is to assume that the string table follows right
- afterwards... */
- len = ((strtab - (char *) symtab) / map->l_info[DT_SYMENT]->d_un.d_val);
- size = ((len * sizeof (fptr_table[0]) + GL(dl_pagesize) - 1)
- & -GL(dl_pagesize));
- /* XXX We don't support here in the moment systems without MAP_ANON.
- There probably are none for IA-64. In case this is proven wrong
- we will have to open /dev/null here and use the file descriptor
- instead of the hard-coded -1. */
- fptr_table = __mmap (NULL, size, PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
- if (fptr_table == MAP_FAILED)
- _dl_signal_error (errno, NULL, NULL, "cannot map pages for fptr table");
-
- map->l_mach.fptr_table_len = len;
- map->l_mach.fptr_table = fptr_table;
- return fptr_table;
-}
-
-Elf64_Addr
-__ia64_make_fptr (struct link_map *map, const Elf64_Sym *sym, Elf64_Addr ip)
-{
- Elf64_Addr *ftab = map->l_mach.fptr_table;
- const Elf64_Sym *symtab;
- Elf_Symndx symidx;
-
- if (__builtin_expect (!map->l_mach.fptr_table, 0))
- ftab = make_fptr_table (map);
-
- symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
- symidx = sym - symtab;
-
- if (symidx >= map->l_mach.fptr_table_len)
- _dl_signal_error (0, NULL, NULL,
- "internal error: symidx out of range of fptr table");
-
- if (!ftab[symidx])
- {
- /* GOT has already been relocated in elf_get_dynamic_info -
- don't try to relocate it again. */
- ftab[symidx] = make_fdesc (ip, map->l_info[DT_PLTGOT]->d_un.d_ptr);
-#if 0
- {
- const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
- struct local *l;
-
- asm ("addl %0 = @gprel (local), gp" : "=r" (l));
- if (l->root != &l->boot_table || l->boot_table.first_unused > 20)
- _dl_debug_printf ("created fdesc symbol `%s' at %lx\n",
- strtab + sym->st_name, ftab[symidx]);
- }
-#endif
- }
-
- return ftab[symidx];
-}
-
-void
-_dl_unmap (struct link_map *map)
-{
- Elf64_Addr *ftab = map->l_mach.fptr_table;
- struct ia64_fdesc *head = NULL, *tail = NULL;
- size_t i;
-
- __munmap ((void *) map->l_map_start, map->l_map_end - map->l_map_start);
-
- if (!ftab)
- return;
-
- /* String together the fdesc structures that are being freed. */
- for (i = 0; i < map->l_mach.fptr_table_len; ++i)
- {
- if (ftab[i])
- {
- *(struct ia64_fdesc **) ftab[i] = head;
- head = (struct ia64_fdesc *) ftab[i];
- if (!tail)
- tail = head;
- }
- }
-
- /* Prepend the new list to the free_list: */
- if (tail)
- {
- lock (&local);
- {
- *(struct ia64_fdesc **) tail = local.free_list;
- local.free_list = head;
- }
- unlock (&local);
- }
-
- __munmap (ftab,
- map->l_mach.fptr_table_len * sizeof (map->l_mach.fptr_table[0]));
- map->l_mach.fptr_table = NULL;
-}
-
-Elf64_Addr
-_dl_lookup_address (const void *address)
-{
- Elf64_Addr addr = (Elf64_Addr) address;
- struct ia64_fdesc_table *t;
- unsigned long int i;
-
- for (t = local.root; t != NULL; t = t->next)
- {
- i = (struct ia64_fdesc *) addr - &t->fdesc[0];
- if (i < t->first_unused && addr == (Elf64_Addr) &t->fdesc[i])
- {
- addr = t->fdesc[i].ip;
- break;
- }
- }
- return addr;
-}