mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-08 18:30:18 +00:00
Not needed anymore.
This commit is contained in:
parent
362f5ae2c1
commit
0a7fb82685
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user