This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

PATCH: Add generic function descripto support


On Thu, Sep 27, 2001 at 10:45:25AM -0700, David Mosberger wrote:
> 
>   HJ> BTW, I think glibc should have a generic implementation for
>   HJ> function descriptors so that ia64, hppa, ... can share the code.
> 
> That sounds like a good idea.
> 

Here is a patch. Someone should try to convert hppa. It shouldn't be
too hard.


H.J.
---
2001-09-28  H.J. Lu  <hjl@gnu.org>

	* sysdeps/generic/dl-fptr.c (lock): Block signals before
	acquiring lock.
	(unlock): Unblock signals after releasing lock.

	* sysdeps/ia64/dl-lookupcfg.h (_dl_symbol_address): Remove
	`const'.

	* sysdeps/ia64/dl-machine.h: Include <dl-fptr.h>.
	(IA64_BOOT_FPTR_TABLE_LEN): Removed.
	(ia64_fdesc): Likewise.
	(ia64_fdesc_table): Likewise.
	(__ia64_make_fptr): Likewise.
	(__ia64_init_bootstrap_fdesc_table): Replace __ia64_boot_fptr_table
	with _dl_boot_fptr_table.
	(elf_machine_runtime_setup): Replace `struct ia64_fdesc' with
	`struct fdesc'.
	(elf_machine_rela): Replace __ia64_make_fptr with _dl_make_fptr.

	* sysdeps/generic/dl-fptr.h: New.
	* sysdeps/ia64/dl-fptr.h: New.
	* sysdeps/generic/dl-symaddr.c: New.

	* sysdeps/ia64/dl-symaddr.c: Removed.

	* sysdeps/ia64/dl-fptr.c: Moved to ...
	* sysdeps/generic/dl-fptr.c: Here.

--- libc/sysdeps/generic/dl-fptr.c.fptr	Thu Sep 27 19:39:58 2001
+++ libc/sysdeps/generic/dl-fptr.c	Fri Sep 28 06:45:10 2001
@@ -0,0 +1,299 @@
+/* Manage function descriptors.  Generic version.
+   Copyright (C) 1999, 2000, 2001 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 <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-fptr.h>
+#ifdef _LIBC_REENTRANT
+# include <pt-machine.h>
+# include <signal.h>
+# include <time.h>
+#else
+# include <atomicity.h>
+#endif
+
+#ifndef ELF_MACHINE_BOOT_FPTR_TABLE_LEN
+/* ELF_MACHINE_BOOT_FPTR_TABLE_LEN should be greater than the number of
+   dynamic symbols in ld.so.  */
+#define ELF_MACHINE_BOOT_FPTR_TABLE_LEN 256
+#endif
+
+#ifndef ELF_MACHINE_LOAD_ADDRESS
+# error "ELF_MACHINE_LOAD_ADDRESS is not defined."
+#endif
+
+ElfW(Addr) _dl_boot_fptr_table [ELF_MACHINE_BOOT_FPTR_TABLE_LEN];
+
+static struct local
+  {
+    struct fdesc_table *root;
+    struct 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 fdesc_table boot_table;
+    struct 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);				\
+  __sigprocmask (SIG_BLOCK, &(l)->full_sigset, &_saved_set);	\
+								\
+  while (testandset ((int *) &(l)->lock))			\
+    {								\
+      struct timespec ts;					\
+      if (i > 0)						\
+	{							\
+	  --i;							\
+	  continue;						\
+	}							\
+      ts.tv_sec = 0;						\
+      ts.tv_nsec = 1*1000*1000;					\
+      __nanosleep (&ts, NULL);					\
+    }
+# define unlock(l)						\
+  (l)->lock = 0;						\
+  __sigprocmask (SIG_SETMASK, &_saved_set, NULL);		\
+}
+#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 fdesc *
+new_fdesc_table (struct local *l)
+{
+  size_t size = l->npages * _dl_pagesize;
+  struct fdesc_table *new_table;
+  struct 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 fdesc);
+  fdesc = &new_table->fdesc[0];
+  new_table->first_unused = 1;
+  new_table->next = l->root;
+  l->root = new_table;
+  return fdesc;
+}
+
+static ElfW(Addr)
+make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp)
+{
+  struct fdesc *fdesc = NULL;
+  struct fdesc_table *t;
+  unsigned int old;
+  struct local *l;
+
+  ELF_MACHINE_LOAD_ADDRESS (l, local);
+
+  t = l->root;
+  while (1)
+    {
+      old = t->first_unused;
+      if (old >= t->len)
+	break;
+      else if (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 fdesc *) fdesc->ip;
+      }
+    else
+      fdesc = new_fdesc_table (l);	/* create new fdesc table */
+  }
+  unlock (l);
+
+ install:
+  fdesc->ip = ip;
+  fdesc->gp = gp;
+
+  return (ElfW(Addr)) fdesc;
+}
+
+static inline ElfW(Addr) *
+make_fptr_table (struct link_map *map)
+{
+  const ElfW(Sym) *symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]);
+  const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
+  ElfW(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]) + _dl_pagesize - 1) & -_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;
+}
+
+ElfW(Addr)
+_dl_make_fptr (struct link_map *map, const ElfW(Sym) *sym,
+	       ElfW(Addr) ip)
+{
+  ElfW(Addr) *ftab = map->l_mach.fptr_table;
+  const ElfW(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;
+
+	ELF_MACHINE_LOAD_ADDRESS (l, local);
+	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)
+{
+  ElfW(Addr) *ftab = map->l_mach.fptr_table;
+  struct 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 fdesc **) ftab[i] = head;
+	  head = (struct fdesc *) ftab[i];
+	  if (!tail)
+	    tail = head;
+	}
+    }
+
+  /* Prepend the new list to the free_list: */
+  if (tail)
+    {
+      lock (&local);
+      {
+	*(struct 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;
+}
+
+ElfW(Addr)
+_dl_lookup_address (const void *address)
+{
+  ElfW(Addr) addr = (ElfW(Addr)) address;
+  struct fdesc_table *t;
+  unsigned long int i;
+
+  for (t = local.root; t != NULL; t = t->next)
+    {
+      i = (struct fdesc *) addr - &t->fdesc[0];
+      if (i < t->first_unused && addr == (ElfW(Addr)) &t->fdesc[i])
+	{
+	  addr = t->fdesc[i].ip;
+	  break;
+	}
+    }
+  return addr;
+}
--- libc/sysdeps/generic/dl-fptr.h.fptr	Thu Sep 27 19:40:05 2001
+++ libc/sysdeps/generic/dl-fptr.h	Thu Sep 27 19:40:56 2001
@@ -0,0 +1,44 @@
+/* Function descriptors. Generic version.
+   Copyright (C) 1995, 1996, 1997, 2000, 2001 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.  */
+
+#ifndef dl_fptr_h
+#define dl_fptr_h 1
+
+/* An FDESC is a function descriptor.  */
+
+struct fdesc
+  {
+    ElfW(Addr) ip;	/* code entry point */
+    ElfW(Addr) gp;	/* global pointer */
+  };
+
+struct fdesc_table
+  {
+    struct fdesc_table *next;
+    unsigned int len;			/* # of entries in fdesc table */
+    volatile unsigned int first_unused;	/* index of first available entry */
+    struct fdesc fdesc[0];
+  };
+
+extern ElfW(Addr) _dl_boot_fptr_table [];
+
+extern ElfW(Addr) _dl_make_fptr (struct link_map *, const ElfW(Sym) *,
+				 ElfW(Addr));
+
+#endif /* !dl_fptr_h */
--- libc/sysdeps/generic/dl-symaddr.c.fptr	Thu Sep 27 16:48:17 2001
+++ libc/sysdeps/generic/dl-symaddr.c	Thu Sep 27 19:38:18 2001
@@ -0,0 +1,33 @@
+/* Get the symbol address.  Generic version.
+   Copyright (C) 1999, 2000, 2001 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 <ldsodefs.h>
+#include <dl-fptr.h>
+
+void *
+_dl_symbol_address (struct link_map *map, const ElfW(Sym) *ref)
+{
+  Elf64_Addr value = (map ? map->l_addr : 0) + ref->st_value;
+
+  /* Return the pointer to function descriptor. */
+  if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC)
+    return (void *) _dl_make_fptr (map, ref, value);
+  else
+    return (void *) value;
+}
--- libc/sysdeps/ia64/dl-fptr.c.fptr	Sat Sep  8 10:16:44 2001
+++ libc/sysdeps/ia64/dl-fptr.c	Fri Sep 28 06:57:55 2001
@@ -1,287 +0,0 @@
-/* Manage function descriptors.  IA-64 version.
-   Copyright (C) 1999, 2000, 2001 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 <pt-machine.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 (testandset ((int *) &(l)->lock))			\
-    {								\
-      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);		\
-  (l)->lock = 0;						\
-}
-#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 * _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 ("addl %0 = @gprel (local), 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]) + _dl_pagesize - 1) & -_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;
-}
--- libc/sysdeps/ia64/dl-fptr.h.fptr	Thu Sep 27 17:03:56 2001
+++ libc/sysdeps/ia64/dl-fptr.h	Thu Sep 27 19:39:14 2001
@@ -0,0 +1,36 @@
+/* Function descriptors.  IA64 version.
+   Copyright (C) 1995, 1996, 1997, 2000, 2001 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.  */
+
+#ifndef dl_ia64_fptr_h
+#define dl_ia64_fptr_h 1
+
+#include <ia64intrin.h>
+#include <sysdeps/generic/dl-fptr.h>
+
+#define compare_and_swap(ptr,old,new)				\
+	__sync_bool_compare_and_swap ((ptr), (old), (new))
+
+/* There are currently 123 dynamic symbols in ld.so.
+   ELF_MACHINE_BOOT_FPTR_TABLE_LEN needs to be at least that big.  */
+#define ELF_MACHINE_BOOT_FPTR_TABLE_LEN	200
+
+#define ELF_MACHINE_LOAD_ADDRESS(var,symbol)			\
+	asm ("addl %0 = @gprel (" #symbol "), gp" : "=r" (var));
+
+#endif /* !dl_ia64_fptr_h */
--- libc/sysdeps/ia64/dl-lookupcfg.h.fptr	Thu Sep 27 17:21:37 2001
+++ libc/sysdeps/ia64/dl-lookupcfg.h	Thu Sep 27 17:20:54 2001
@@ -26,7 +26,7 @@
 /* Forward declaration.  */
 struct link_map;
 
-extern void *_dl_symbol_address (const struct link_map *map,
+extern void *_dl_symbol_address (struct link_map *map,
 				 const Elf64_Sym *ref);
 
 #define DL_SYMBOL_ADDRESS(map, ref) _dl_symbol_address(map, ref)
--- libc/sysdeps/ia64/dl-machine.h.fptr	Thu Aug 30 16:09:10 2001
+++ libc/sysdeps/ia64/dl-machine.h	Thu Sep 27 17:06:35 2001
@@ -26,44 +26,21 @@
 #include <string.h>
 #include <link.h>
 #include <errno.h>
-
+#include <dl-fptr.h>
 
 /* Translate a processor specific dynamic tag to the index
    in l_info array.  */
 #define DT_IA_64(x) (DT_IA_64_##x - DT_LOPROC + DT_NUM)
 
-/* There are currently 123 dynamic symbols in ld.so.
-   IA64_BOOT_FPTR_TABLE_LEN needs to be at least that big.  */
-#define IA64_BOOT_FPTR_TABLE_LEN	200
-
-/* An FDESC is a function descriptor.  */
-
-struct ia64_fdesc
-  {
-    Elf64_Addr ip;	/* code entry point */
-    Elf64_Addr gp;	/* global pointer */
-  };
-
-struct ia64_fdesc_table
-  {
-    struct ia64_fdesc_table *next;
-    unsigned int len;			/* # of entries in fdesc table */
-    volatile unsigned int first_unused;	/* index of first available entry */
-    struct ia64_fdesc fdesc[0];
-  };
-
-extern Elf64_Addr __ia64_make_fptr (struct link_map *, const Elf64_Sym *,
-				    Elf64_Addr);
-
 static inline void
 __ia64_init_bootstrap_fdesc_table (struct link_map *map)
 {
   Elf64_Addr *boot_table;
 
   /* careful: this will be called before got has been relocated... */
-  asm ("addl %0 = @gprel (__ia64_boot_fptr_table), gp" : "=r"(boot_table));
+  asm ("addl %0 = @gprel (_dl_boot_fptr_table), gp" : "=r"(boot_table));
 
-  map->l_mach.fptr_table_len = IA64_BOOT_FPTR_TABLE_LEN;
+  map->l_mach.fptr_table_len = ELF_MACHINE_BOOT_FPTR_TABLE_LEN;
   map->l_mach.fptr_table = boot_table;
 }
 
@@ -142,7 +119,7 @@ elf_machine_runtime_setup (struct link_m
 
       /* This function will be called to perform the relocation.  */
       if (!profile)
-	doit = (Elf64_Addr) ((struct ia64_fdesc *) &_dl_runtime_resolve)->ip;
+	doit = (Elf64_Addr) ((struct fdesc *) &_dl_runtime_resolve)->ip;
       else
 	{
 	  if (_dl_name_match_p (_dl_profile, l))
@@ -151,7 +128,7 @@ elf_machine_runtime_setup (struct link_m
 		 want profiling and the timers are started.  */
 	      _dl_profile_map = l;
 	    }
-	  doit = (Elf64_Addr) ((struct ia64_fdesc *) &_dl_runtime_profile)->ip;
+	  doit = (Elf64_Addr) ((struct fdesc *) &_dl_runtime_profile)->ip;
 	}
 
       reserve[1] = doit;
@@ -555,7 +532,7 @@ elf_machine_rela (struct link_map *map,
 	      return;
 	    }
 	  else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_FPTR64LSB))
-	    value = __ia64_make_fptr (sym_map, sym, value);
+	    value = _dl_make_fptr (sym_map, sym, value);
 	  else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_PCREL64LSB))
 	    value -= (Elf64_Addr) reloc_addr & -16;
 	  else
--- libc/sysdeps/ia64/dl-symaddr.c.fptr	Wed Jul 25 17:22:42 2001
+++ libc/sysdeps/ia64/dl-symaddr.c	Fri Sep 28 06:57:55 2001
@@ -1,33 +0,0 @@
-/* Get the symbol address.  IA-64 version.
-   Copyright (C) 1999, 2000, 2001 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 <ldsodefs.h>
-#include <dl-machine.h>
-
-void *
-_dl_symbol_address (const struct link_map *map, const Elf64_Sym *ref)
-{
-  Elf64_Addr value = (map ? map->l_addr : 0) + ref->st_value;
-
-  /* On ia64, we have to return the pointer to function descriptor. */
-  if (ELFW(ST_TYPE) (ref->st_info) == STT_FUNC)
-    return (void *) __ia64_make_fptr (map, ref, value);
-  else
-    return (void *) value;
-}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]