about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2005-02-08 10:05:09 +0000
committerJakub Jelinek <jakub@redhat.com>2005-02-08 10:05:09 +0000
commitd585b66fa4d11059948f466c9080a6826932358d (patch)
tree8b06692920852c297635b46a7d616c3066f95fac /sysdeps
parente7cbcee4982d8caa809a91c9cfef5fda67445f0a (diff)
downloadglibc-d585b66fa4d11059948f466c9080a6826932358d.tar.gz
glibc-d585b66fa4d11059948f466c9080a6826932358d.tar.xz
glibc-d585b66fa4d11059948f466c9080a6826932358d.zip
Updated to fedora-glibc-20050208T0948 cvs/fedora-glibc-2_3_4-6
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/alpha/bits/link.h69
-rw-r--r--sysdeps/alpha/dl-machine.h168
-rw-r--r--sysdeps/alpha/dl-trampoline.S361
-rw-r--r--sysdeps/alpha/fpu/bits/mathinline.h17
-rw-r--r--sysdeps/alpha/libc-tls.c2
-rw-r--r--sysdeps/arm/bits/link.h4
-rw-r--r--sysdeps/arm/bits/linkmap.h4
-rw-r--r--sysdeps/generic/bits/link.h5
-rw-r--r--sysdeps/generic/bits/linkmap.h4
-rw-r--r--sysdeps/generic/dl-fptr.h2
-rw-r--r--sysdeps/generic/dl-lookupcfg.h25
-rw-r--r--sysdeps/generic/dl-tls.c411
-rw-r--r--sysdeps/generic/dl-trampoline.c1
-rw-r--r--sysdeps/generic/ldsodefs.h198
-rw-r--r--sysdeps/generic/libc-start.c24
-rw-r--r--sysdeps/generic/libc-tls.c11
-rw-r--r--sysdeps/generic/syslog.c429
-rw-r--r--sysdeps/generic/unsecvars.h17
-rw-r--r--sysdeps/generic/wordexp.c60
-rw-r--r--sysdeps/hppa/bits/link.h6
-rw-r--r--sysdeps/hppa/bits/linkmap.h6
-rw-r--r--sysdeps/hppa/dl-lookupcfg.h6
-rw-r--r--sysdeps/i386/Makefile4
-rw-r--r--sysdeps/i386/bits/link.h65
-rw-r--r--sysdeps/i386/bits/linkmap.h5
-rw-r--r--sysdeps/i386/dl-machine.h149
-rw-r--r--sysdeps/i386/dl-trampoline.S182
-rw-r--r--sysdeps/ia64/bits/link.h68
-rw-r--r--sysdeps/ia64/bits/linkmap.h5
-rw-r--r--sysdeps/ia64/dl-lookupcfg.h19
-rw-r--r--sysdeps/ia64/dl-machine.h159
-rw-r--r--sysdeps/ia64/dl-trampoline.S537
-rw-r--r--sysdeps/ia64/fpu/e_logl.c1
-rw-r--r--sysdeps/ia64/libc-tls.c2
-rw-r--r--sysdeps/linkmap.h4
-rw-r--r--sysdeps/m68k/bits/link.h58
-rw-r--r--sysdeps/m68k/dl-machine.h49
-rw-r--r--sysdeps/m68k/dl-trampoline.S129
-rw-r--r--sysdeps/mach/hurd/tls.h9
-rw-r--r--sysdeps/powerpc/powerpc32/bits/link.h62
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.c5
-rw-r--r--sysdeps/powerpc/powerpc32/dl-machine.h175
-rw-r--r--sysdeps/powerpc/powerpc32/dl-trampoline.S174
-rw-r--r--sysdeps/powerpc/powerpc64/bits/link.h109
-rw-r--r--sysdeps/powerpc/powerpc64/dl-lookupcfg.h22
-rw-r--r--sysdeps/powerpc/powerpc64/dl-machine.h96
-rw-r--r--sysdeps/powerpc/powerpc64/dl-trampoline.S196
-rw-r--r--sysdeps/powerpc/tst-stack-align.h47
-rw-r--r--sysdeps/s390/bits/link.h120
-rw-r--r--sysdeps/s390/bits/linkmap.h13
-rw-r--r--sysdeps/s390/bits/string.h14
-rw-r--r--sysdeps/s390/s390-32/dl-machine.h151
-rw-r--r--sysdeps/s390/s390-32/dl-trampoline.S133
-rw-r--r--sysdeps/s390/s390-64/dl-machine.h137
-rw-r--r--sysdeps/s390/s390-64/dl-trampoline.S126
-rw-r--r--sysdeps/sh/bits/link.h75
-rw-r--r--sysdeps/sh/bits/linkmap.h5
-rw-r--r--sysdeps/sh/dl-machine.h297
-rw-r--r--sysdeps/sh/dl-trampoline.S431
-rw-r--r--sysdeps/sh/sh4/Versions5
-rw-r--r--sysdeps/sh/sh4/dl-machine.h2
-rw-r--r--sysdeps/sh/sh4/dl-trampoline.S2
-rw-r--r--sysdeps/unix/i386/sysdep.S12
-rw-r--r--sysdeps/unix/rewinddir.c3
-rw-r--r--sysdeps/unix/sysv/linux/alpha/oldglob.c3
-rw-r--r--sysdeps/unix/sysv/linux/dl-execstack.c26
-rw-r--r--sysdeps/unix/sysv/linux/futimes.c66
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h37
-rw-r--r--sysdeps/unix/sysv/linux/init-first.c1
-rw-r--r--sysdeps/unix/sysv/linux/kernel-features.h7
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S10
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S10
-rw-r--r--sysdeps/unix/sysv/linux/syslog.c10
-rw-r--r--sysdeps/x86_64/bits/link.h125
-rw-r--r--sysdeps/x86_64/bits/linkmap.h14
-rw-r--r--sysdeps/x86_64/dl-machine.h157
-rw-r--r--sysdeps/x86_64/dl-trampoline.S188
77 files changed, 4550 insertions, 1791 deletions
diff --git a/sysdeps/alpha/bits/link.h b/sysdeps/alpha/bits/link.h
new file mode 100644
index 0000000000..429faff432
--- /dev/null
+++ b/sysdeps/alpha/bits/link.h
@@ -0,0 +1,69 @@
+/* Copyright (C) 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on Alpha.  */
+typedef struct La_alpha_regs
+{
+  uint64_t lr_r26;
+  uint64_t lr_sp;
+  uint64_t lr_r16;
+  uint64_t lr_r17;
+  uint64_t lr_r18;
+  uint64_t lr_r19;
+  uint64_t lr_r20;
+  uint64_t lr_r21;
+  double lr_f16;
+  double lr_f17;
+  double lr_f18;
+  double lr_f19;
+  double lr_f20;
+  double lr_f21;
+} La_alpha_regs;
+
+/* Return values for calls from PLT on Alpha.  */
+typedef struct La_alpha_retval
+{
+  uint64_t lrv_r0;
+  uint64_t lrv_r1;
+  double lrv_f0;
+  double lrv_f1;
+} La_alpha_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_alpha_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
+				         uintptr_t *__refcook,
+				         uintptr_t *__defcook,
+				         La_alpha_regs *__regs,
+				         unsigned int *__flags,
+				         const char *__symname,
+				         long int *__framesizep);
+extern unsigned int la_alpha_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
+					  uintptr_t *__refcook,
+					  uintptr_t *__defcook,
+					  const La_alpha_regs *__inregs,
+					  La_alpha_retval *__outregs,
+					  const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 780a3a57fd..4166e8c498 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -108,19 +108,20 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
       plt = D_PTR (l, l_info[DT_PLTGOT]);
 
       /* This function will be called to perform the relocation.  */
-      if (!profile)
-        *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve;
-      else
+      if (__builtin_expect (profile, 0))
 	{
 	  *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_profile;
 
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    {
 	      /* This is the object we are looking for.  Say that we really
 		 want profiling and the timers are started.  */
 	      GL(dl_profile_map) = l;
 	    }
 	}
+      else
+        *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve;
 
       /* Identify this shared object */
       *(Elf64_Addr *)(plt + 24) = (Elf64_Addr) l;
@@ -156,143 +157,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name, IMB)	\
-  extern void tramp_name (void);				\
-  asm ( "\
-	.globl " #tramp_name "					\n\
-	.ent " #tramp_name "					\n\
-" #tramp_name ":						\n\
-	lda	$sp, -44*8($sp)					\n\
-	.frame	$sp, 44*8, $26					\n\
-	/* Preserve all integer registers that C normally	\n\
-	   doesn't.  */						\n\
-	stq	$26, 0*8($sp)					\n\
-	stq	$0, 1*8($sp)					\n\
-	stq	$1, 2*8($sp)					\n\
-	stq	$2, 3*8($sp)					\n\
-	stq	$3, 4*8($sp)					\n\
-	stq	$4, 5*8($sp)					\n\
-	stq	$5, 6*8($sp)					\n\
-	stq	$6, 7*8($sp)					\n\
-	stq	$7, 8*8($sp)					\n\
-	stq	$8, 9*8($sp)					\n\
-	stq	$16, 10*8($sp)					\n\
-	stq	$17, 11*8($sp)					\n\
-	stq	$18, 12*8($sp)					\n\
-	stq	$19, 13*8($sp)					\n\
-	stq	$20, 14*8($sp)					\n\
-	stq	$21, 15*8($sp)					\n\
-	stq	$22, 16*8($sp)					\n\
-	stq	$23, 17*8($sp)					\n\
-	stq	$24, 18*8($sp)					\n\
-	stq	$25, 19*8($sp)					\n\
-	stq	$29, 20*8($sp)					\n\
-	stt	$f0, 21*8($sp)					\n\
-	stt	$f1, 22*8($sp)					\n\
-	stt	$f10, 23*8($sp)					\n\
-	stt	$f11, 24*8($sp)					\n\
-	stt	$f12, 25*8($sp)					\n\
-	stt	$f13, 26*8($sp)					\n\
-	stt	$f14, 27*8($sp)					\n\
-	stt	$f15, 28*8($sp)					\n\
-	stt	$f16, 29*8($sp)					\n\
-	stt	$f17, 30*8($sp)					\n\
-	stt	$f18, 31*8($sp)					\n\
-	stt	$f19, 32*8($sp)					\n\
-	stt	$f20, 33*8($sp)					\n\
-	stt	$f21, 34*8($sp)					\n\
-	stt	$f22, 35*8($sp)					\n\
-	stt	$f23, 36*8($sp)					\n\
-	stt	$f24, 37*8($sp)					\n\
-	stt	$f25, 38*8($sp)					\n\
-	stt	$f26, 39*8($sp)					\n\
-	stt	$f27, 40*8($sp)					\n\
-	stt	$f28, 41*8($sp)					\n\
-	stt	$f29, 42*8($sp)					\n\
-	stt	$f30, 43*8($sp)					\n\
-	.mask	0x27ff01ff, -44*8				\n\
-	.fmask	0xfffffc03, -(44-21)*8				\n\
-	/* Set up our $gp */					\n\
-	br	$gp, .+4					\n\
-	ldgp	$gp, 0($gp)					\n\
-	.prologue 0						\n\
-	/* Set up the arguments for fixup: */			\n\
-	/* $16 = link_map out of plt0 */			\n\
-	/* $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24 */\n\
-	/* $18 = return address */				\n\
-	subq	$28, $27, $17					\n\
-	ldq	$16, 8($27)					\n\
-	subq	$17, 20, $17					\n\
-	mov	$26, $18					\n\
-	addq	$17, $17, $17					\n\
-	/* Do the fixup */					\n\
-	bsr	$26, " #fixup_name "	!samegp			\n\
-	/* Move the destination address into position.  */	\n\
-	mov	$0, $27						\n\
-	/* Restore program registers.  */			\n\
-	ldq	$26, 0*8($sp)					\n\
-	ldq	$0, 1*8($sp)					\n\
-	ldq	$1, 2*8($sp)					\n\
-	ldq	$2, 3*8($sp)					\n\
-	ldq	$3, 4*8($sp)					\n\
-	ldq	$4, 5*8($sp)					\n\
-	ldq	$5, 6*8($sp)					\n\
-	ldq	$6, 7*8($sp)					\n\
-	ldq	$7, 8*8($sp)					\n\
-	ldq	$8, 9*8($sp)					\n\
-	ldq	$16, 10*8($sp)					\n\
-	ldq	$17, 11*8($sp)					\n\
-	ldq	$18, 12*8($sp)					\n\
-	ldq	$19, 13*8($sp)					\n\
-	ldq	$20, 14*8($sp)					\n\
-	ldq	$21, 15*8($sp)					\n\
-	ldq	$22, 16*8($sp)					\n\
-	ldq	$23, 17*8($sp)					\n\
-	ldq	$24, 18*8($sp)					\n\
-	ldq	$25, 19*8($sp)					\n\
-	ldq	$29, 20*8($sp)					\n\
-	ldt	$f0, 21*8($sp)					\n\
-	ldt	$f1, 22*8($sp)					\n\
-	ldt	$f10, 23*8($sp)					\n\
-	ldt	$f11, 24*8($sp)					\n\
-	ldt	$f12, 25*8($sp)					\n\
-	ldt	$f13, 26*8($sp)					\n\
-	ldt	$f14, 27*8($sp)					\n\
-	ldt	$f15, 28*8($sp)					\n\
-	ldt	$f16, 29*8($sp)					\n\
-	ldt	$f17, 30*8($sp)					\n\
-	ldt	$f18, 31*8($sp)					\n\
-	ldt	$f19, 32*8($sp)					\n\
-	ldt	$f20, 33*8($sp)					\n\
-	ldt	$f21, 34*8($sp)					\n\
-	ldt	$f22, 35*8($sp)					\n\
-	ldt	$f23, 36*8($sp)					\n\
-	ldt	$f24, 37*8($sp)					\n\
-	ldt	$f25, 38*8($sp)					\n\
-	ldt	$f26, 39*8($sp)					\n\
-	ldt	$f27, 40*8($sp)					\n\
-	ldt	$f28, 41*8($sp)					\n\
-	ldt	$f29, 42*8($sp)					\n\
-	ldt	$f30, 43*8($sp)					\n\
-	/* Flush the Icache after having modified the .plt code.  */\n\
-	" #IMB "						\n\
-	/* Clean up and turn control to the destination */	\n\
-	lda	$sp, 44*8($sp)					\n\
-	jmp	$31, ($27)					\n\
-	.end " #tramp_name)
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE				\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup, imb);	\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup, /* nop */);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE				\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup, imb);	\
-  strong_alias (_dl_runtime_resolve, _dl_runtime_profile);
-#endif
-
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
    its return value is the user program's entry point.  */
@@ -501,9 +365,13 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
   return value + reloc->r_addend;
 }
 
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER	alpha_gnu_pltenter
+#define ARCH_LA_PLTEXIT		alpha_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
@@ -555,26 +423,16 @@ elf_machine_rela (struct link_map *map,
       return;
   else
     {
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       Elf64_Addr sym_value;
       Elf64_Addr sym_raw_value;
 
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
-      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       sym_raw_value = sym_value = reloc->r_addend;
-      if (sym)
+      if (sym_map)
 	{
 	  sym_raw_value += sym->st_value;
 	  sym_value = sym_raw_value + sym_map->l_addr;
 	}
-#else
-      Elf64_Addr loadbase = RESOLVE (&sym, version, r_type);
-      sym_raw_value = sym_value = reloc->r_addend;
-      if (sym)
-	{
-	  sym_raw_value += sym->st_value;
-	  sym_value = sym_raw_value + loadbase;
-	}
-#endif
 
       if (r_type == R_ALPHA_GLOB_DAT)
 	*reloc_addr = sym_value;
@@ -680,4 +538,4 @@ elf_machine_lazy_rel (struct link_map *map,
     _dl_reloc_bad_type (map, r_type, 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/alpha/dl-trampoline.S b/sysdeps/alpha/dl-trampoline.S
new file mode 100644
index 0000000000..42350836ef
--- /dev/null
+++ b/sysdeps/alpha/dl-trampoline.S
@@ -0,0 +1,361 @@
+/* PLT trampolines.  Alpha version.
+   Copyright (C) 2005 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 <sysdep.h>
+
+	.set noat
+
+	.globl	_dl_runtime_resolve
+	.ent	_dl_runtime_resolve
+
+#undef FRAMESIZE
+#define FRAMESIZE	44*8
+
+_dl_runtime_resolve:
+	lda	$30, -FRAMESIZE($30)
+	.frame	$30, FRAMESIZE, $26
+	/* Preserve all registers that C normally doesn't.  */
+	stq	$26, 0*8($30)
+	stq	$0, 1*8($30)
+	stq	$1, 2*8($30)
+	stq	$2, 3*8($30)
+	stq	$3, 4*8($30)
+	stq	$4, 5*8($30)
+	stq	$5, 6*8($30)
+	stq	$6, 7*8($30)
+	stq	$7, 8*8($30)
+	stq	$8, 9*8($30)
+	stq	$16, 10*8($30)
+	stq	$17, 11*8($30)
+	stq	$18, 12*8($30)
+	stq	$19, 13*8($30)
+	stq	$20, 14*8($30)
+	stq	$21, 15*8($30)
+	stq	$22, 16*8($30)
+	stq	$23, 17*8($30)
+	stq	$24, 18*8($30)
+	stq	$25, 19*8($30)
+	stq	$29, 20*8($30)
+	stt	$f0, 21*8($30)
+	stt	$f1, 22*8($30)
+	stt	$f10, 23*8($30)
+	stt	$f11, 24*8($30)
+	stt	$f12, 25*8($30)
+	stt	$f13, 26*8($30)
+	stt	$f14, 27*8($30)
+	stt	$f15, 28*8($30)
+	stt	$f16, 29*8($30)
+	stt	$f17, 30*8($30)
+	stt	$f18, 31*8($30)
+	stt	$f19, 32*8($30)
+	stt	$f20, 33*8($30)
+	stt	$f21, 34*8($30)
+	stt	$f22, 35*8($30)
+	stt	$f23, 36*8($30)
+	stt	$f24, 37*8($30)
+	stt	$f25, 38*8($30)
+	stt	$f26, 39*8($30)
+	stt	$f27, 40*8($30)
+	stt	$f28, 41*8($30)
+	stt	$f29, 42*8($30)
+	stt	$f30, 43*8($30)
+	.mask	0x27ff01ff, -FRAMESIZE
+	.fmask	0xfffffc03, -FRAMESIZE+21*8
+	/* Set up our GP.  */
+	br	$29, .+4
+	ldgp	$29, 0($29)
+	.prologue 0
+	/* Set up the arguments for _dl_fixup:
+	   $16 = link_map out of plt0
+	   $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24
+	   $18 = return address
+	*/
+	subq	$28, $27, $17
+	ldq	$16, 8($27)
+	subq	$17, 20, $17
+	mov	$26, $18
+	addq	$17, $17, $17
+	bsr	$26, _dl_fixup	!samegp
+
+	/* Move the destination address into position.  */
+	mov	$0, $27
+	/* Restore program registers.  */
+	ldq	$26, 0*8($30)
+	ldq	$0, 1*8($30)
+	ldq	$1, 2*8($30)
+	ldq	$2, 3*8($30)
+	ldq	$3, 4*8($30)
+	ldq	$4, 5*8($30)
+	ldq	$5, 6*8($30)
+	ldq	$6, 7*8($30)
+	ldq	$7, 8*8($30)
+	ldq	$8, 9*8($30)
+	ldq	$16, 10*8($30)
+	ldq	$17, 11*8($30)
+	ldq	$18, 12*8($30)
+	ldq	$19, 13*8($30)
+	ldq	$20, 14*8($30)
+	ldq	$21, 15*8($30)
+	ldq	$22, 16*8($30)
+	ldq	$23, 17*8($30)
+	ldq	$24, 18*8($30)
+	ldq	$25, 19*8($30)
+	ldq	$29, 20*8($30)
+	ldt	$f0, 21*8($30)
+	ldt	$f1, 22*8($30)
+	ldt	$f10, 23*8($30)
+	ldt	$f11, 24*8($30)
+	ldt	$f12, 25*8($30)
+	ldt	$f13, 26*8($30)
+	ldt	$f14, 27*8($30)
+	ldt	$f15, 28*8($30)
+	ldt	$f16, 29*8($30)
+	ldt	$f17, 30*8($30)
+	ldt	$f18, 31*8($30)
+	ldt	$f19, 32*8($30)
+	ldt	$f20, 33*8($30)
+	ldt	$f21, 34*8($30)
+	ldt	$f22, 35*8($30)
+	ldt	$f23, 36*8($30)
+	ldt	$f24, 37*8($30)
+	ldt	$f25, 38*8($30)
+	ldt	$f26, 39*8($30)
+	ldt	$f27, 40*8($30)
+	ldt	$f28, 41*8($30)
+	ldt	$f29, 42*8($30)
+	ldt	$f30, 43*8($30)
+	/* Flush the Icache after having modified the .plt code.  */
+	imb
+	/* Clean up and turn control to the destination */
+	lda	$30, FRAMESIZE($30)
+	jmp	$31, ($27)
+
+	.end	_dl_runtime_resolve
+
+	.globl	_dl_runtime_profile
+	.usepv	_dl_runtime_profile, no
+	.type	_dl_runtime_profile, @function
+
+	/* We save the registers in a different order than desired by
+	   .mask/.fmask, so we have to use explicit cfi directives.  */
+	cfi_startproc
+
+.macro savei regno, offset
+	stq	$\regno, \offset($30)
+	cfi_rel_offset(\regno, \offset)
+.endm
+
+.macro savef regno, offset
+	stt	$f\regno, \offset($30)
+	cfi_rel_offset(\regno+32, \offset)
+.endm
+
+#undef FRAMESIZE
+#define FRAMESIZE	50*8
+
+_dl_runtime_profile:
+	lda	$30, -FRAMESIZE($30)
+	cfi_adjust_cfa_offset (FRAMESIZE)
+
+	/* Preserve all argument registers.  This also constructs the
+	   La_alpha_regs structure.  */
+	savei	26, 0*8
+	savei	16, 2*8
+	savei	17, 3*8
+	savei	18, 4*8
+	savei	19, 5*8
+	savei	20, 6*8
+	savei	21, 7*8
+	lda	$16, FRAMESIZE($30)
+	savef	16, 8*8
+	savef	17, 9*8
+	savef	18, 10*8
+	savef	19, 11*8
+	savef	20, 12*8
+	savef	21, 13*8
+	stq	$16, 1*8($30)
+
+	/* Preserve all registers that C normally doesn't.  */
+	savei	0, 14*8
+	savei	1, 15*8
+	savei	2, 16*8
+	savei	3, 17*8
+	savei	4, 18*8
+	savei	5, 19*8
+	savei	6, 20*8
+	savei	7, 21*8
+	savei	8, 22*8
+	savei	22, 23*8
+	savei	23, 24*8
+	savei	24, 25*8
+	savei	25, 26*8
+	savei	29, 27*8
+	savef	0, 28*8
+	savef	1, 29*8
+	savef	10, 30*8
+	savef	11, 31*8
+	savef	12, 32*8
+	savef	13, 33*8
+	savef	14, 34*8
+	savef	15, 35*8
+	savef	22, 36*8
+	savef	23, 37*8
+	savef	24, 38*8
+	savef	25, 39*8
+	savef	26, 40*8
+	savef	27, 41*8
+	savef	28, 42*8
+	savef	29, 43*8
+	savef	30, 44*8
+
+	/* Set up our GP.  */
+	br	$29, .+4
+	ldgp	$29, 0($29)
+
+	/* Set up the arguments for _dl_profile_fixup:
+	   $16 = link_map out of plt0
+	   $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24
+	   $18 = return address
+	   $19 = La_alpha_regs address
+	   $20 = framesize address
+	*/
+	subq	$28, $27, $17
+	ldq	$16, 8($27)
+	subq	$17, 20, $17
+	mov	$26, $18
+	addq	$17, $17, $17
+	lda	$19, 0($30)
+	lda	$20, 45*8($30)
+	stq	$16, 48*8($30)
+	stq	$17, 49*8($30)
+
+	bsr	$26, _dl_profile_fixup	!samegp
+
+	/* Discover if we're wrapping this call.  */
+	ldq	$18, 45*8($30)
+	bge	$18, 1f
+
+	/* Move the destination address into position.  */
+	mov	$0, $27
+	/* Restore program registers.  */
+	ldq	$26, 0*8($30)
+	ldq	$16, 2*8($30)
+	ldq	$17, 3*8($30)
+	ldq	$18, 4*8($30)
+	ldq	$19, 5*8($30)
+	ldq	$20, 6*8($30)
+	ldq	$21, 7*8($30)
+	ldt	$f16, 8*8($30)
+	ldt	$f17, 9*8($30)
+	ldt	$f18, 10*8($30)
+	ldt	$f19, 11*8($30)
+	ldt	$f20, 12*8($30)
+	ldt	$f21, 13*8($30)
+	ldq	$0, 14*8($30)
+	ldq	$1, 15*8($30)
+	ldq	$2, 16*8($30)
+	ldq	$3, 17*8($30)
+	ldq	$4, 18*8($30)
+	ldq	$5, 19*8($30)
+	ldq	$6, 20*8($30)
+	ldq	$7, 21*8($30)
+	ldq	$8, 22*8($30)
+	ldq	$22, 23*8($30)
+	ldq	$23, 24*8($30)
+	ldq	$24, 25*8($30)
+	ldq	$25, 26*8($30)
+	ldq	$29, 27*8($30)
+	ldt	$f0, 28*8($30)
+	ldt	$f1, 29*8($30)
+	ldt	$f10, 30*8($30)
+	ldt	$f11, 31*8($30)
+	ldt	$f12, 32*8($30)
+	ldt	$f13, 33*8($30)
+	ldt	$f14, 34*8($30)
+	ldt	$f15, 35*8($30)
+	ldt	$f22, 36*8($30)
+	ldt	$f23, 37*8($30)
+	ldt	$f24, 38*8($30)
+	ldt	$f25, 39*8($30)
+	ldt	$f26, 40*8($30)
+	ldt	$f27, 41*8($30)
+	ldt	$f28, 42*8($30)
+	ldt	$f29, 43*8($30)
+	ldt	$f30, 44*8($30)
+
+	/* Clean up and turn control to the destination.  */
+	lda	$30, FRAMESIZE($30)
+	jmp	$31, ($27)
+
+1:
+	/* Create a frame pointer and allocate a new argument frame.  */
+	savei	15, 45*8
+	mov	$30, $15
+	cfi_def_cfa_register (15)
+	addq	$18, 15, $18
+	bic	$18, 15, $18
+	subq	$30, $18, $30
+
+	/* Save the call destination around memcpy.  */
+	stq	$0, 46*8($30)
+
+	/* Copy the stack arguments into place.  */
+	lda	$16, 0($30)
+	lda	$17, FRAMESIZE($15)
+	jsr	$26, memcpy
+	ldgp	$29, 0($26)
+
+	/* Reload the argument registers.  */
+	ldq	$27, 46*8($30)
+	ldq	$16, 2*8($15)
+	ldq	$17, 3*8($15)
+	ldq	$18, 4*8($15)
+	ldq	$19, 5*8($15)
+	ldq	$20, 6*8($15)
+	ldq	$21, 7*8($15)
+	ldt	$f16, 8*8($15)
+	ldt	$f17, 9*8($15)
+	ldt	$f18, 10*8($15)
+	ldt	$f19, 11*8($15)
+	ldt	$f20, 12*8($15)
+	ldt	$f21, 13*8($15)
+
+	jsr	$26, ($27), 0
+	ldgp	$29, 0($26)
+
+	/* Set up for call to _dl_call_pltexit.  */
+	ldq	$16, 48($15)
+	ldq	$17, 49($15)
+	stq	$0, 46*8($15)
+	lda	$18, 0($15)
+	stq	$1, 47*8($15)
+	lda	$19, 46*8($15)
+	stt	$f0, 48*8($15)
+	stt	$f1, 49*8($15)
+	bsr	$26, _dl_call_pltexit	!samegp
+
+	mov	$15, $30
+	cfi_def_cfa_register (30)
+	ldq	$26, 0($30)
+	ldq	$15, 45*8($30)
+	lda	$30, FRAMESIZE($30)
+	ret
+
+	cfi_endproc
+	.size	_dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/alpha/fpu/bits/mathinline.h b/sysdeps/alpha/fpu/bits/mathinline.h
index 187bd42f33..87d40058c3 100644
--- a/sysdeps/alpha/fpu/bits/mathinline.h
+++ b/sysdeps/alpha/fpu/bits/mathinline.h
@@ -46,7 +46,8 @@
 #if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \
     && defined __OPTIMIZE__
 
-#define __inline_copysign(NAME, TYPE)					\
+#if !__GNUC_PREREQ (4, 0)
+# define __inline_copysign(NAME, TYPE)					\
 __MATH_INLINE TYPE							\
 __NTH (NAME (TYPE __x, TYPE __y))					\
 {									\
@@ -60,19 +61,11 @@ __inline_copysign (copysignf, float)
 __inline_copysign (__copysign, double)
 __inline_copysign (copysign, double)
 
-#undef __MATH_INLINE_copysign
+# undef __inline_copysign
+#endif
 
 
-#if __GNUC_PREREQ (2, 8)
-__MATH_INLINE float
-__NTH (__fabsf (float __x)) { return __builtin_fabsf (__x); }
-__MATH_INLINE float
-__NTH (fabsf (float __x)) { return __builtin_fabsf (__x); }
-__MATH_INLINE double
-__NTH (__fabs (double __x)) { return __builtin_fabs (__x); }
-__MATH_INLINE double
-__NTH (fabs (double __x)) { return __builtin_fabs (__x); }
-#else
+#if !__GNUC_PREREQ (2, 8)
 # define __inline_fabs(NAME, TYPE)			\
 __MATH_INLINE TYPE					\
 __NTH (NAME (TYPE __x))					\
diff --git a/sysdeps/alpha/libc-tls.c b/sysdeps/alpha/libc-tls.c
index 434d5d9313..a3b68e928f 100644
--- a/sysdeps/alpha/libc-tls.c
+++ b/sysdeps/alpha/libc-tls.c
@@ -31,7 +31,7 @@ void *
 __tls_get_addr (tls_index *ti)
 {
   dtv_t *dtv = THREAD_DTV ();
-  return (char *) dtv[1].pointer + ti->ti_offset;
+  return (char *) dtv[1].pointer.val + ti->ti_offset;
 }
 
 #endif
diff --git a/sysdeps/arm/bits/link.h b/sysdeps/arm/bits/link.h
index 648976d7d2..e69de29bb2 100644
--- a/sysdeps/arm/bits/link.h
+++ b/sysdeps/arm/bits/link.h
@@ -1,4 +0,0 @@
-struct link_map_machine
-  {
-    Elf32_Addr plt; /* Address of .plt */
-  };
diff --git a/sysdeps/arm/bits/linkmap.h b/sysdeps/arm/bits/linkmap.h
new file mode 100644
index 0000000000..648976d7d2
--- /dev/null
+++ b/sysdeps/arm/bits/linkmap.h
@@ -0,0 +1,4 @@
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt */
+  };
diff --git a/sysdeps/generic/bits/link.h b/sysdeps/generic/bits/link.h
index 470b4d3e5f..6b4f811c25 100644
--- a/sysdeps/generic/bits/link.h
+++ b/sysdeps/generic/bits/link.h
@@ -1,4 +1 @@
-struct link_map_machine
-  {
-    /* empty by default */
-  };
+#error "Architecture-specific definition needed."
diff --git a/sysdeps/generic/bits/linkmap.h b/sysdeps/generic/bits/linkmap.h
new file mode 100644
index 0000000000..470b4d3e5f
--- /dev/null
+++ b/sysdeps/generic/bits/linkmap.h
@@ -0,0 +1,4 @@
+struct link_map_machine
+  {
+    /* empty by default */
+  };
diff --git a/sysdeps/generic/dl-fptr.h b/sysdeps/generic/dl-fptr.h
index 8156981e6e..d47fb7b635 100644
--- a/sysdeps/generic/dl-fptr.h
+++ b/sysdeps/generic/dl-fptr.h
@@ -36,6 +36,8 @@ struct fdesc_table
     struct fdesc fdesc[0];
   };
 
+struct link_map;
+
 extern ElfW(Addr) _dl_boot_fptr_table [];
 
 extern ElfW(Addr) _dl_make_fptr (struct link_map *, const ElfW(Sym) *,
diff --git a/sysdeps/generic/dl-lookupcfg.h b/sysdeps/generic/dl-lookupcfg.h
index f48cb0a844..2b29989600 100644
--- a/sysdeps/generic/dl-lookupcfg.h
+++ b/sysdeps/generic/dl-lookupcfg.h
@@ -1,5 +1,5 @@
 /* Configuration of lookup functions.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004 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
@@ -17,16 +17,13 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-/* Some platforms need more information from the symbol lookup function
-   than just the address.  But this is not generally the case.
-
-   However, because of how _dl_sym and _dl_tls_symaddr are written, every
-   platform needs it when we support TLS.  */
-
-#include <tls.h>		/* Defines USE_TLS (or doesn't).  */
-
-#ifdef USE_TLS
-# define DL_LOOKUP_RETURNS_MAP
-#else
-# undef DL_LOOKUP_RETURNS_MAP
-#endif
+/* The type of the return value of fixup/profile_fixup.  */
+#define DL_FIXUP_VALUE_TYPE ElfW(Addr)
+/* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address
+   and a link map.  */
+#define DL_FIXUP_MAKE_VALUE(map, addr) (addr)
+/* Extract the code address from a value of type DL_FIXUP_MAKE_VALUE.
+ */
+#define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
+#define DL_FIXUP_VALUE_ADDR(value) (value)
+#define DL_FIXUP_ADDR_VALUE(addr) (addr)
diff --git a/sysdeps/generic/dl-tls.c b/sysdeps/generic/dl-tls.c
index 2282dda9cc..099742ceff 100644
--- a/sysdeps/generic/dl-tls.c
+++ b/sysdeps/generic/dl-tls.c
@@ -1,5 +1,5 @@
 /* Thread-local storage handling in the ELF dynamic linker.  Generic version.
-   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004, 2005 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
@@ -18,6 +18,8 @@
    02111-1307 USA.  */
 
 #include <assert.h>
+#include <errno.h>
+#include <libintl.h>
 #include <signal.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -65,7 +67,10 @@ _dl_next_tls_modid (void)
       /* Note that this branch will never be executed during program
 	 start since there are no gaps at that time.  Therefore it
 	 does not matter that the dl_tls_dtv_slotinfo is not allocated
-	 yet when the function is called for the first times.  */
+	 yet when the function is called for the first times.
+
+	 NB: the offset +1 is due to the fact that DTV[0] is used
+	 for something else.  */
       result = GL(dl_tls_static_nelem) + 1;
       /* If the following would not be true we mustn't have assumed
 	 there is a gap.  */
@@ -88,11 +93,11 @@ _dl_next_tls_modid (void)
 	}
       while ((runp = runp->next) != NULL);
 
-      if (result >= GL(dl_tls_max_dtv_idx))
+      if (result > GL(dl_tls_max_dtv_idx))
 	{
 	  /* The new index must indeed be exactly one higher than the
 	     previous high.  */
-	  assert (result == GL(dl_tls_max_dtv_idx));
+	  assert (result == GL(dl_tls_max_dtv_idx) + 1);
 
 	  /* There is no gap anymore.  */
 	  GL(dl_tls_dtv_gaps) = false;
@@ -116,10 +121,9 @@ void
 internal_function
 _dl_determine_tlsoffset (void)
 {
-  struct dtv_slotinfo *slotinfo;
   size_t max_align = TLS_TCB_ALIGN;
-  size_t offset, freetop = 0, freebottom = 0;
-  size_t cnt;
+  size_t freetop = 0;
+  size_t freebottom = 0;
 
   /* The first element of the dtv slot info list is allocated.  */
   assert (GL(dl_tls_dtv_slotinfo_list) != NULL);
@@ -127,7 +131,7 @@ _dl_determine_tlsoffset (void)
      dl_tls_dtv_slotinfo_list list.  */
   assert (GL(dl_tls_dtv_slotinfo_list)->next == NULL);
 
-  slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
+  struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
 
   /* Determining the offset of the various parts of the static TLS
      block has several dependencies.  In addition we have to work
@@ -159,9 +163,9 @@ _dl_determine_tlsoffset (void)
 
 # if TLS_TCB_AT_TP
   /* We simply start with zero.  */
-  offset = 0;
+  size_t offset = 0;
 
-  for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt)
+  for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt)
     {
       assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len);
 
@@ -206,9 +210,9 @@ _dl_determine_tlsoffset (void)
 			    + TLS_TCB_SIZE);
 # elif TLS_DTV_AT_TP
   /* The TLS blocks start right after the TCB.  */
-  offset = TLS_TCB_SIZE;
+  size_t offset = TLS_TCB_SIZE;
 
-  for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt)
+  for (size_t cnt = 0; slotinfo[cnt].map != NULL; ++cnt)
     {
       assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len);
 
@@ -225,8 +229,8 @@ _dl_determine_tlsoffset (void)
 	  if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop)
 	    {
 	      slotinfo[cnt].map->l_tls_offset = off - firstbyte;
-	      freebottom = off + slotinfo[cnt].map->l_tls_blocksize
-			   - firstbyte;
+	      freebottom = (off + slotinfo[cnt].map->l_tls_blocksize
+			    - firstbyte);
 	      continue;
 	    }
 	}
@@ -357,14 +361,14 @@ _dl_allocate_tls_storage (void)
 
       /* Clear the TCB data structure.  We can't ask the caller (i.e.
 	 libpthread) to do it, because we will initialize the DTV et al.  */
-      memset (result, 0, TLS_TCB_SIZE);
+      memset (result, '\0', TLS_TCB_SIZE);
 # elif TLS_DTV_AT_TP
       result = (char *) result + size - GL(dl_tls_static_size);
 
       /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it.
 	 We can't ask the caller (i.e. libpthread) to do it, because we will
 	 initialize the DTV et al.  */
-      memset ((char *) result - TLS_PRE_TCB_SIZE, 0,
+      memset ((char *) result - TLS_PRE_TCB_SIZE, '\0',
 	      TLS_PRE_TCB_SIZE + TLS_TCB_SIZE);
 # endif
 
@@ -388,10 +392,11 @@ _dl_allocate_tls_init (void *result)
   dtv_t *dtv = GET_DTV (result);
   struct dtv_slotinfo_list *listp;
   size_t total = 0;
+  size_t maxgen = 0;
 
-  /* We have to look prepare the dtv for all currently loaded
-     modules using TLS.  For those which are dynamically loaded we
-     add the values indicating deferred allocation.  */
+  /* We have to prepare the dtv for all currently loaded modules using
+     TLS.  For those which are dynamically loaded we add the values
+     indicating deferred allocation.  */
   listp = GL(dl_tls_dtv_slotinfo_list);
   while (1)
     {
@@ -411,11 +416,16 @@ _dl_allocate_tls_init (void *result)
 	    /* Unused entry.  */
 	    continue;
 
+	  /* Keep track of the maximum generation number.  This might
+	     not be the generation counter.  */
+	  maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
+
 	  if (map->l_tls_offset == NO_TLS_OFFSET)
 	    {
 	      /* For dynamically loaded modules we simply store
 		 the value indicating deferred allocation.  */
-	      dtv[map->l_tls_modid].pointer = TLS_DTV_UNALLOCATED;
+	      dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED;
+	      dtv[map->l_tls_modid].pointer.is_static = false;
 	      continue;
 	    }
 
@@ -431,7 +441,8 @@ _dl_allocate_tls_init (void *result)
 # endif
 
 	  /* Copy the initialization image and clear the BSS part.  */
-	  dtv[map->l_tls_modid].pointer = dest;
+	  dtv[map->l_tls_modid].pointer.val = dest;
+	  dtv[map->l_tls_modid].pointer.is_static = true;
 	  memset (__mempcpy (dest, map->l_tls_initimage,
 			     map->l_tls_initimage_size), '\0',
 		  map->l_tls_blocksize - map->l_tls_initimage_size);
@@ -445,6 +456,9 @@ _dl_allocate_tls_init (void *result)
       assert (listp != NULL);
     }
 
+  /* The DTV version is up-to-date now.  */
+  dtv[0].counter = maxgen;
+
   return result;
 }
 rtld_hidden_def (_dl_allocate_tls_init)
@@ -466,6 +480,12 @@ _dl_deallocate_tls (void *tcb, bool dealloc_tcb)
 {
   dtv_t *dtv = GET_DTV (tcb);
 
+  /* We need to free the memory allocated for non-static TLS.  */
+  for (size_t cnt = 0; cnt < dtv[-1].counter; ++cnt)
+    if (! dtv[1 + cnt].pointer.is_static
+	&& dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED)
+      free (dtv[1 + cnt].pointer.val);
+
   /* The array starts with dtv[-1].  */
 #ifdef SHARED
   if (dtv != GL(dl_initial_dtv))
@@ -524,166 +544,172 @@ allocate_and_init (struct link_map *map)
 }
 
 
-/* The generic dynamic and local dynamic model cannot be used in
-   statically linked applications.  */
-void *
-__tls_get_addr (GET_ADDR_ARGS)
+struct link_map *
+_dl_update_slotinfo (unsigned long int req_modid)
 {
-  dtv_t *dtv = THREAD_DTV ();
   struct link_map *the_map = NULL;
-  void *p;
+  dtv_t *dtv = THREAD_DTV ();
 
-  if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
+  /* The global dl_tls_dtv_slotinfo array contains for each module
+     index the generation counter current when the entry was created.
+     This array never shrinks so that all module indices which were
+     valid at some time can be used to access it.  Before the first
+     use of a new module index in this function the array was extended
+     appropriately.  Access also does not have to be guarded against
+     modifications of the array.  It is assumed that pointer-size
+     values can be read atomically even in SMP environments.  It is
+     possible that other threads at the same time dynamically load
+     code and therefore add to the slotinfo list.  This is a problem
+     since we must not pick up any information about incomplete work.
+     The solution to this is to ignore all dtv slots which were
+     created after the one we are currently interested.  We know that
+     dynamic loading for this module is completed and this is the last
+     load operation we know finished.  */
+  unsigned long int idx = req_modid;
+  struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list);
+
+  while (idx >= listp->len)
     {
-      struct dtv_slotinfo_list *listp;
-      size_t idx;
-
-      /* The global dl_tls_dtv_slotinfo array contains for each module
-	 index the generation counter current when the entry was
-	 created.  This array never shrinks so that all module indices
-	 which were valid at some time can be used to access it.
-	 Before the first use of a new module index in this function
-	 the array was extended appropriately.  Access also does not
-	 have to be guarded against modifications of the array.  It is
-	 assumed that pointer-size values can be read atomically even
-	 in SMP environments.  It is possible that other threads at
-	 the same time dynamically load code and therefore add to the
-	 slotinfo list.  This is a problem since we must not pick up
-	 any information about incomplete work.  The solution to this
-	 is to ignore all dtv slots which were created after the one
-	 we are currently interested.  We know that dynamic loading
-	 for this module is completed and this is the last load
-	 operation we know finished.  */
-      idx = GET_ADDR_MODULE;
-      listp = GL(dl_tls_dtv_slotinfo_list);
-      while (idx >= listp->len)
-	{
-	  idx -= listp->len;
-	  listp = listp->next;
-	}
+      idx -= listp->len;
+      listp = listp->next;
+    }
 
-      if (dtv[0].counter < listp->slotinfo[idx].gen)
+  if (dtv[0].counter < listp->slotinfo[idx].gen)
+    {
+      /* The generation counter for the slot is higher than what the
+	 current dtv implements.  We have to update the whole dtv but
+	 only those entries with a generation counter <= the one for
+	 the entry we need.  */
+      size_t new_gen = listp->slotinfo[idx].gen;
+      size_t total = 0;
+
+      /* We have to look through the entire dtv slotinfo list.  */
+      listp =  GL(dl_tls_dtv_slotinfo_list);
+      do
 	{
-	  /* The generation counter for the slot is higher than what
-	     the current dtv implements.  We have to update the whole
-	     dtv but only those entries with a generation counter <=
-	     the one for the entry we need.  */
-	  size_t new_gen = listp->slotinfo[idx].gen;
-	  size_t total = 0;
-
-	  /* We have to look through the entire dtv slotinfo list.  */
-	  listp =  GL(dl_tls_dtv_slotinfo_list);
-	  do
+	  for (size_t cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
 	    {
-	      size_t cnt;
-
-	      for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt)
+	      size_t gen = listp->slotinfo[cnt].gen;
+
+	      if (gen > new_gen)
+		/* This is a slot for a generation younger than the
+		   one we are handling now.  It might be incompletely
+		   set up so ignore it.  */
+		continue;
+
+	      /* If the entry is older than the current dtv layout we
+		 know we don't have to handle it.  */
+	      if (gen <= dtv[0].counter)
+		continue;
+
+	      /* If there is no map this means the entry is empty.  */
+	      struct link_map *map = listp->slotinfo[cnt].map;
+	      if (map == NULL)
 		{
-		  size_t gen = listp->slotinfo[cnt].gen;
-		  struct link_map *map;
-		  size_t modid;
-
-		  if (gen > new_gen)
-		    /* This is a slot for a generation younger than
-		       the one we are handling now.  It might be
-		       incompletely set up so ignore it.  */
-		    continue;
-
-		  /* If the entry is older than the current dtv layout
-		     we know we don't have to handle it.  */
-		  if (gen <= dtv[0].counter)
-		    continue;
-
-		  /* If there is no map this means the entry is empty.  */
-		  map = listp->slotinfo[cnt].map;
-		  if (map == NULL)
+		  /* If this modid was used at some point the memory
+		     might still be allocated.  */
+		  if (! dtv[total + cnt].pointer.is_static
+		      && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
 		    {
-		      /* If this modid was used at some point the memory
-			 might still be allocated.  */
-		      if (dtv[total + cnt].pointer != TLS_DTV_UNALLOCATED)
-			{
-			  free (dtv[total + cnt].pointer);
-			  dtv[total + cnt].pointer = TLS_DTV_UNALLOCATED;
-			}
-
-		      continue;
+		      free (dtv[total + cnt].pointer.val);
+		      dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
 		    }
 
-		  /* Check whether the current dtv array is large enough.  */
-		  modid = map->l_tls_modid;
-		  assert (total + cnt == modid);
-		  if (dtv[-1].counter < modid)
+		  continue;
+		}
+
+	      /* Check whether the current dtv array is large enough.  */
+	      size_t modid = map->l_tls_modid;
+	      assert (total + cnt == modid);
+	      if (dtv[-1].counter < modid)
+		{
+		  /* Reallocate the dtv.  */
+		  dtv_t *newp;
+		  size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
+		  size_t oldsize = dtv[-1].counter;
+
+		  assert (map->l_tls_modid <= newsize);
+
+		  if (dtv == GL(dl_initial_dtv))
 		    {
-		      /* Reallocate the dtv.  */
-		      dtv_t *newp;
-		      size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS;
-		      size_t oldsize = dtv[-1].counter;
-
-		      assert (map->l_tls_modid <= newsize);
-
-		      if (dtv == GL(dl_initial_dtv))
-			{
-			  /* This is the initial dtv that was allocated
-			     during rtld startup using the dl-minimal.c
-			     malloc instead of the real malloc.  We can't
-			     free it, we have to abandon the old storage.  */
-
-			  newp = malloc ((2 + newsize) * sizeof (dtv_t));
-			  if (newp == NULL)
-			    oom ();
-			  memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t));
-			}
-		      else
-			{
-			  newp = realloc (&dtv[-1],
-					  (2 + newsize) * sizeof (dtv_t));
-			  if (newp == NULL)
-			    oom ();
-			}
-
-		      newp[0].counter = newsize;
-
-		      /* Clear the newly allocated part.  */
-		      memset (newp + 2 + oldsize, '\0',
-			      (newsize - oldsize) * sizeof (dtv_t));
-
-		      /* Point dtv to the generation counter.  */
-		      dtv = &newp[1];
-
-		      /* Install this new dtv in the thread data
-			 structures.  */
-		      INSTALL_NEW_DTV (dtv);
+		      /* This is the initial dtv that was allocated
+			 during rtld startup using the dl-minimal.c
+			 malloc instead of the real malloc.  We can't
+			 free it, we have to abandon the old storage.  */
+
+		      newp = malloc ((2 + newsize) * sizeof (dtv_t));
+		      if (newp == NULL)
+			oom ();
+		      memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t));
 		    }
+		  else
+		    {
+		      newp = realloc (&dtv[-1],
+				      (2 + newsize) * sizeof (dtv_t));
+		      if (newp == NULL)
+			oom ();
+		    }
+
+		  newp[0].counter = newsize;
+
+		  /* Clear the newly allocated part.  */
+		  memset (newp + 2 + oldsize, '\0',
+			  (newsize - oldsize) * sizeof (dtv_t));
 
-		  /* If there is currently memory allocate for this
-		     dtv entry free it.  */
-		  /* XXX Ideally we will at some point create a memory
-		     pool.  */
-		  if (dtv[modid].pointer != TLS_DTV_UNALLOCATED)
-		    /* Note that free is called for NULL is well.  We
-		       deallocate even if it is this dtv entry we are
-		       supposed to load.  The reason is that we call
-		       memalign and not malloc.  */
-		    free (dtv[modid].pointer);
-
-		  /* This module is loaded dynamically- We defer
-		     memory allocation.  */
-		  dtv[modid].pointer = TLS_DTV_UNALLOCATED;
-
-		  if (modid == GET_ADDR_MODULE)
-		    the_map = map;
+		  /* Point dtv to the generation counter.  */
+		  dtv = &newp[1];
+
+		  /* Install this new dtv in the thread data
+		     structures.  */
+		  INSTALL_NEW_DTV (dtv);
 		}
 
-	      total += listp->len;
+	      /* If there is currently memory allocate for this
+		 dtv entry free it.  */
+	      /* XXX Ideally we will at some point create a memory
+		 pool.  */
+	      if (! dtv[modid].pointer.is_static
+		  && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED)
+		/* Note that free is called for NULL is well.  We
+		   deallocate even if it is this dtv entry we are
+		   supposed to load.  The reason is that we call
+		   memalign and not malloc.  */
+		free (dtv[modid].pointer.val);
+
+	      /* This module is loaded dynamically- We defer memory
+		 allocation.  */
+	      dtv[modid].pointer.is_static = false;
+	      dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
+
+	      if (modid == req_modid)
+		the_map = map;
 	    }
-	  while ((listp = listp->next) != NULL);
 
-	  /* This will be the new maximum generation counter.  */
-	  dtv[0].counter = new_gen;
+	  total += listp->len;
 	}
+      while ((listp = listp->next) != NULL);
+
+      /* This will be the new maximum generation counter.  */
+      dtv[0].counter = new_gen;
     }
 
-  p = dtv[GET_ADDR_MODULE].pointer;
+  return the_map;
+}
+
+
+/* The generic dynamic and local dynamic model cannot be used in
+   statically linked applications.  */
+void *
+__tls_get_addr (GET_ADDR_ARGS)
+{
+  dtv_t *dtv = THREAD_DTV ();
+  struct link_map *the_map = NULL;
+  void *p;
+
+  if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0))
+    the_map = _dl_update_slotinfo (GET_ADDR_MODULE);
+
+  p = dtv[GET_ADDR_MODULE].pointer.val;
 
   if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0))
     {
@@ -703,11 +729,74 @@ __tls_get_addr (GET_ADDR_ARGS)
 	  the_map = listp->slotinfo[idx].map;
 	}
 
-      p = dtv[GET_ADDR_MODULE].pointer = allocate_and_init (the_map);
+      p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map);
+      dtv[GET_ADDR_MODULE].pointer.is_static = false;
     }
 
   return (char *) p + GET_ADDR_OFFSET;
 }
 # endif
 
+
+
+void
+_dl_add_to_slotinfo (struct link_map  *l)
+{
+  /* Now that we know the object is loaded successfully add
+     modules containing TLS data to the dtv info table.  We
+     might have to increase its size.  */
+  struct dtv_slotinfo_list *listp;
+  struct dtv_slotinfo_list *prevp;
+  size_t idx = l->l_tls_modid;
+
+  /* Find the place in the dtv slotinfo list.  */
+  listp = GL(dl_tls_dtv_slotinfo_list);
+  prevp = NULL;		/* Needed to shut up gcc.  */
+  do
+    {
+      /* Does it fit in the array of this list element?  */
+      if (idx < listp->len)
+	break;
+      idx -= listp->len;
+      prevp = listp;
+      listp = listp->next;
+    }
+  while (listp != NULL);
+
+  if (listp == NULL)
+    {
+      /* When we come here it means we have to add a new element
+	 to the slotinfo list.  And the new module must be in
+	 the first slot.  */
+      assert (idx == 0);
+
+      listp = prevp->next = (struct dtv_slotinfo_list *)
+	malloc (sizeof (struct dtv_slotinfo_list)
+		+ TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+      if (listp == NULL)
+	{
+	  /* We ran out of memory.  We will simply fail this
+	     call but don't undo anything we did so far.  The
+	     application will crash or be terminated anyway very
+	     soon.  */
+
+	  /* We have to do this since some entries in the dtv
+	     slotinfo array might already point to this
+	     generation.  */
+	  ++GL(dl_tls_generation);
+
+	  _dl_signal_error (ENOMEM, "dlopen", NULL, N_("\
+cannot create TLS data structures"));
+	}
+
+      listp->len = TLS_SLOTINFO_SURPLUS;
+      listp->next = NULL;
+      memset (listp->slotinfo, '\0',
+	      TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo));
+    }
+
+  /* Add the information into the slotinfo data structure.  */
+  listp->slotinfo[idx].map = l;
+  listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1;
+}
 #endif	/* use TLS */
diff --git a/sysdeps/generic/dl-trampoline.c b/sysdeps/generic/dl-trampoline.c
new file mode 100644
index 0000000000..3ca89f3879
--- /dev/null
+++ b/sysdeps/generic/dl-trampoline.c
@@ -0,0 +1 @@
+#error "Architecture specific PLT trampolines must be defined."
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index ec68e1a565..08039e18ca 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1,5 +1,5 @@
 /* Run-time dynamic linker data structures for loaded ELF shared objects.
-   Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1995-2003, 2004, 2005 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
@@ -52,23 +52,15 @@ __BEGIN_DECLS
   most architectures the entry is already relocated - but for some not
   and we need to relocate at access time.  */
 #ifdef DL_RO_DYN_SECTION
-# define D_PTR(map,i) (map->i->d_un.d_ptr + map->l_addr)
+# define D_PTR(map, i) ((map)->i->d_un.d_ptr + (map)->l_addr)
 #else
-# define D_PTR(map,i) map->i->d_un.d_ptr
+# define D_PTR(map, i) (map)->i->d_un.d_ptr
 #endif
 
-/* On some platforms more information than just the address of the symbol
-   is needed from the lookup functions.  In this case we return the whole
-   link map.  */
-#ifdef DL_LOOKUP_RETURNS_MAP
+/* Result of the lookup functions and how to retrieve the base address.  */
 typedef struct link_map *lookup_t;
 # define LOOKUP_VALUE(map) map
-# define LOOKUP_VALUE_ADDRESS(map) (map ? map->l_addr : 0)
-#else
-typedef ElfW(Addr) lookup_t;
-# define LOOKUP_VALUE(map) map->l_addr
-# define LOOKUP_VALUE_ADDRESS(address) address
-#endif
+# define LOOKUP_VALUE_ADDRESS(map) ((map) ? (map)->l_addr : 0)
 
 /* on some architectures a pointer to a function is not just a pointer
    to the actual code of the function but rather an architecture
@@ -182,6 +174,133 @@ enum allowmask
   };
 
 
+/* Type for list of auditing interfaces.  */
+struct La_i86_regs;
+struct La_i86_retval;
+struct La_x86_64_regs;
+struct La_x86_64_retval;
+struct La_ppc32_regs;
+struct La_ppc32_retval;
+struct La_ppc64_regs;
+struct La_ppc64_retval;
+struct La_sh_regs;
+struct La_sh_retval;
+struct La_m68k_regs;
+struct La_m68k_retval;
+struct La_alpha_regs;
+struct La_alpha_retval;
+struct La_s390_32_regs;
+struct La_s390_32_retval;
+struct La_s390_64_regs;
+struct La_s390_64_retval;
+struct La_ia64_regs;
+struct La_ia64_retval;
+
+struct audit_ifaces
+{
+  void (*activity) (uintptr_t *, unsigned int);
+  char *(*objsearch) (const char *, uintptr_t *, unsigned int);
+  unsigned int (*objopen) (struct link_map *, Lmid_t, uintptr_t *);
+  void (*preinit) (uintptr_t *);
+  union
+  {
+    uintptr_t (*symbind32) (Elf32_Sym *, unsigned int, uintptr_t *,
+			    uintptr_t *, unsigned int *, const char *);
+    uintptr_t (*symbind64) (Elf64_Sym *, unsigned int, uintptr_t *,
+			    uintptr_t *, unsigned int *, const char *);
+  };
+  union
+  {
+    Elf32_Addr (*i86_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+				    uintptr_t *, struct La_i86_regs *,
+				    unsigned int *, const char *name,
+				    long int *framesizep);
+    Elf64_Addr (*x86_64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+				       uintptr_t *, struct La_x86_64_regs *,
+				       unsigned int *, const char *name,
+				       long int *framesizep);
+    Elf32_Addr (*ppc32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+				      uintptr_t *, struct La_ppc32_regs *,
+				      unsigned int *, const char *name,
+				      long int *framesizep);
+    Elf64_Addr (*ppc64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+				      uintptr_t *, struct La_ppc64_regs *,
+				      unsigned int *, const char *name,
+				      long int *framesizep);
+    uintptr_t (*sh_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+				  uintptr_t *, const struct La_sh_regs *,
+				  unsigned int *, const char *name,
+				  long int *framesizep);
+    Elf32_Addr (*m68k_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+				     uintptr_t *, struct La_m68k_regs *,
+				     unsigned int *, const char *name,
+				     long int *framesizep);
+    Elf64_Addr (*alpha_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+				      uintptr_t *, struct La_alpha_regs *,
+				      unsigned int *, const char *name,
+				      long int *framesizep);
+    Elf32_Addr (*s390_32_gnu_pltenter) (Elf32_Sym *, unsigned int, uintptr_t *,
+					uintptr_t *, struct La_s390_32_regs *,
+					unsigned int *, const char *name,
+					long int *framesizep);
+    Elf64_Addr (*s390_64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+					uintptr_t *, struct La_s390_64_regs *,
+					unsigned int *, const char *name,
+					long int *framesizep);
+    Elf64_Addr (*ia64_gnu_pltenter) (Elf64_Sym *, unsigned int, uintptr_t *,
+				     uintptr_t *, struct La_ia64_regs *,
+				     unsigned int *, const char *name,
+				     long int *framesizep);
+  };
+  union
+  {
+    unsigned int (*i86_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+				     uintptr_t *, const struct La_i86_regs *,
+				     struct La_i86_retval *, const char *);
+    unsigned int (*x86_64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+					uintptr_t *,
+					const struct La_x86_64_regs *,
+					struct La_x86_64_retval *,
+					const char *);
+    unsigned int (*ppc32_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+				       uintptr_t *,
+				       const struct La_ppc32_regs *,
+				       struct La_ppc32_retval *, const char *);
+    unsigned int (*ppc64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+				       uintptr_t *,
+				       const struct La_ppc64_regs *,
+				       struct La_ppc64_retval *, const char *);
+    unsigned int (*sh_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+				    uintptr_t *, const struct La_sh_regs *,
+				    struct La_sh_retval *, const char *);
+    unsigned int (*m68k_gnu_pltexit) (Elf32_Sym *, unsigned int, uintptr_t *,
+				      uintptr_t *, const struct La_m68k_regs *,
+				      struct La_m68k_retval *, const char *);
+    unsigned int (*alpha_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+				       uintptr_t *,
+				       const struct La_alpha_regs *,
+				       struct La_alpha_retval *, const char *);
+    unsigned int (*s390_32_gnu_pltexit) (Elf32_Sym *, unsigned int,
+					 uintptr_t *, uintptr_t *,
+					 const struct La_s390_32_regs *,
+					 struct La_s390_32_retval *,
+					 const char *);
+    unsigned int (*s390_64_gnu_pltexit) (Elf64_Sym *, unsigned int,
+					 uintptr_t *, uintptr_t *,
+					 const struct La_s390_64_regs *,
+					 struct La_s390_64_retval *,
+					 const char *);
+    unsigned int (*ia64_gnu_pltexit) (Elf64_Sym *, unsigned int, uintptr_t *,
+				      uintptr_t *,
+				      const struct La_ia64_regs *,
+				      struct La_ia64_retval *, const char *);
+  };
+  unsigned int (*objclose) (uintptr_t *);
+
+  struct audit_ifaces *next;
+};
+
+
 /* Test whether given NAME matches any of the names of the given object.  */
 extern int _dl_name_match_p (const char *__name, struct link_map *__map)
      internal_function;
@@ -224,7 +343,7 @@ struct rtld_global
 #endif
   EXTERN struct link_namespaces
   {
-    /* And a pointer to the map for the main map.  */
+    /* A pointer to the map for the main map.  */
     struct link_map *_ns_loaded;
     /* Number of object in the _dl_loaded list.  */
     unsigned int _ns_nloaded;
@@ -236,6 +355,8 @@ struct rtld_global
        allocated by rtld.  Later it keeps the size of the map.  It might be
        reset if in _dl_close if the last global object is removed.  */
     size_t _ns_global_scope_alloc;
+    /* Keep track of changes to each namespace' list.  */
+    struct r_debug _ns_debug;
   } _dl_ns[DL_NNS];
 
   /* During the program run we must not modify the global data of
@@ -277,8 +398,12 @@ struct rtld_global
   EXTERN void **(*_dl_error_catch_tsd) (void) __attribute__ ((const));
 #endif
 
-  /* Structure describing the dynamic linker itself.  */
+  /* Structure describing the dynamic linker itself.  We need to
+     reserve memory for the data the audit libraries need.  */
   EXTERN struct link_map _dl_rtld_map;
+#ifdef SHARED
+  struct auditstate audit_data[DL_NNS];
+#endif
 
 #if defined SHARED && defined _LIBC_REENTRANT \
     && defined __rtld_lock_default_lock_recursive
@@ -311,6 +436,7 @@ struct rtld_global
     struct dtv_slotinfo
     {
       size_t gen;
+      bool is_static;
       struct link_map *map;
     } slotinfo[0];
   } *_dl_tls_dtv_slotinfo_list;
@@ -483,32 +609,12 @@ struct rtld_global_ro
      call the function instead of going through the PLT.  The result
      is that we can avoid exporting the functions and we do not jump
      PLT relocations in libc.so.  */
-  const char *(*_dl_get_origin) (void);
-  size_t (*_dl_dst_count) (const char *, int);
-  char *(*_dl_dst_substitute) (struct link_map *, const char *, char *, int);
-  struct link_map *(internal_function *_dl_map_object) (struct link_map *,
-							const char *, int,
-							int, int, int, Lmid_t);
-  void (internal_function *_dl_map_object_deps) (struct link_map *,
-						 struct link_map **,
-						 unsigned int, int, int);
-  void (*_dl_relocate_object) (struct link_map *, struct r_scope_elem *[],
-			       int, int);
-  int (internal_function *_dl_check_map_versions) (struct link_map *, int,
-						   int);
-  void (internal_function *_dl_init) (struct link_map *, int, char **,
-					char **);
-  void (*_dl_debug_state) (void);
-#ifndef MAP_COPY
-  void (*_dl_unload_cache) (void);
-#endif
   void (*_dl_debug_printf) (const char *, ...)
        __attribute__ ((__format__ (__printf__, 1, 2)));
   int (internal_function *_dl_catch_error) (const char **, const char **,
 					    void (*) (void *), void *);
   void (internal_function *_dl_signal_error) (int, const char *, const char *,
 					      const char *);
-  void (internal_function *_dl_start_profile) (void);
   void (*_dl_mcount) (ElfW(Addr) frompc, ElfW(Addr) selfpc);
   lookup_t (internal_function *_dl_lookup_symbol_x) (const char *,
 						     struct link_map *,
@@ -518,7 +624,13 @@ struct rtld_global_ro
 						     int, int,
 						     struct link_map *);
   int (*_dl_check_caller) (const void *, enum allowmask);
+  void *(*_dl_open) (const char *file, int mode, const void *caller_dlopen,
+		     Lmid_t nsid, int argc, char *argv[], char *env[]);
+  void (*_dl_close) (void *map);
 
+  /* List of auditing interfaces.  */
+  struct audit_ifaces *_dl_audit;
+  unsigned int _dl_naudit;
 };
 # define __rtld_global_attribute__
 # ifdef IS_IN_rtld
@@ -793,7 +905,7 @@ rtld_hidden_proto (_dl_debug_state)
 /* Initialize `struct r_debug' if it has not already been done.  The
    argument is the run-time load address of the dynamic linker, to be put
    in the `r_ldbase' member.  Returns the address of the structure.  */
-extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase)
+extern struct r_debug *_dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
      internal_function;
 
 /* Initialize the basic data structure for the search paths.  */
@@ -911,6 +1023,20 @@ extern char *_dl_dst_substitute (struct link_map *l, const char *name,
 extern int _dl_check_caller (const void *caller, enum allowmask mask)
      attribute_hidden;
 
+/* Open the shared object NAME, relocate it, and run its initializer if it
+   hasn't already been run.  MODE is as for `dlopen' (see <dlfcn.h>).  If
+   the object is already opened, returns its existing map.  */
+extern void *_dl_open (const char *name, int mode, const void *caller,
+		       Lmid_t nsid, int argc, char *argv[], char *env[])
+     attribute_hidden;
+
+/* Add module to slot information data.  */
+extern void _dl_add_to_slotinfo (struct link_map  *l) attribute_hidden;
+
+/* Update slot information data for at least the generation of the
+   module with the given index.  */
+extern struct link_map *_dl_update_slotinfo (unsigned long int req_modid);
+
 __END_DECLS
 
 #endif /* ldsodefs.h */
diff --git a/sysdeps/generic/libc-start.c b/sysdeps/generic/libc-start.c
index ad5ebe0911..5bb8a9b352 100644
--- a/sysdeps/generic/libc-start.c
+++ b/sysdeps/generic/libc-start.c
@@ -80,6 +80,10 @@ STATIC int LIBC_START_MAIN (int (*main) (int, char **, char **
 			    void *__unbounded stack_end)
      __attribute__ ((noreturn));
 
+
+/* Note: the fini parameter is ignored here.  It used to be registered
+   with __cxa_atexit.  This had the disadvantage that finalizers were
+   called in more than one place.  */
 STATIC int
 LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 		 int argc, char *__unbounded *__unbounded ubp_av,
@@ -158,10 +162,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
   __libc_init_first (argc, argv, __environ);
 #endif
 
-  /* Register the destructor of the program, if any.  */
-  if (fini)
-    __cxa_atexit ((void (*) (void *)) fini, NULL, NULL);
-
 #ifndef SHARED
   /* Some security at this point.  Prevent starting a SUID binary where
      the standard file descriptors are not opened.  We have to do this
@@ -184,6 +184,22 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 	     );
 
 #ifdef SHARED
+  /* Auditing checkpoint: we have a new object.  */
+  if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+    {
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->preinit != NULL)
+	    afct->preinit (&head->l_audit[cnt].cookie);
+
+	  afct = afct->next;
+	}
+    }
+#endif
+
+#ifdef SHARED
   if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0))
     GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
 #endif
diff --git a/sysdeps/generic/libc-tls.c b/sysdeps/generic/libc-tls.c
index b5ecc36436..b88ede06a2 100644
--- a/sysdeps/generic/libc-tls.c
+++ b/sysdeps/generic/libc-tls.c
@@ -1,5 +1,5 @@
 /* Initialization code for TLS in statically linked application.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 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
@@ -178,17 +178,18 @@ __libc_setup_tls (size_t tcbsize, size_t tcbalign)
 
   /* Initialize the TLS block.  */
 # if TLS_TCB_AT_TP
-  static_dtv[2].pointer = ((char *) tlsblock + tcb_offset
-			   - roundup (memsz, align ?: 1));
+  static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset
+			       - roundup (memsz, align ?: 1));
   static_map.l_tls_offset = roundup (memsz, align ?: 1);
 # elif TLS_DTV_AT_TP
-  static_dtv[2].pointer = (char *) tlsblock + tcb_offset;
+  static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset;
   static_map.l_tls_offset = tcb_offset;
 # else
 #  error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
 # endif
+  static_dtv[2].pointer.is_static = true;
   /* sbrk gives us zero'd memory, so we don't need to clear the remainder.  */
-  memcpy (static_dtv[2].pointer, initimage, filesz);
+  memcpy (static_dtv[2].pointer.val, initimage, filesz);
 
   /* Install the pointer to the dtv.  */
 
diff --git a/sysdeps/generic/syslog.c b/sysdeps/generic/syslog.c
new file mode 100644
index 0000000000..9c8f422aad
--- /dev/null
+++ b/sysdeps/generic/syslog.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 1983, 1988, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)syslog.c	8.4 (Berkeley) 3/18/94";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/uio.h>
+#include <netdb.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <bits/libc-lock.h>
+#include <signal.h>
+#include <locale.h>
+
+#if __STDC__
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#include <libio/iolibio.h>
+#define ftell(s) INTUSE(_IO_ftell) (s)
+
+static int	LogType = SOCK_DGRAM;	/* type of socket connection */
+static int	LogFile = -1;		/* fd for log */
+static int	connected;		/* have done connect */
+static int	LogStat;		/* status bits, set by openlog() */
+static const char *LogTag;		/* string to tag the entry with */
+static int	LogFacility = LOG_USER;	/* default facility code */
+static int	LogMask = 0xff;		/* mask of priorities to be logged */
+extern char	*__progname;		/* Program name, from crt0. */
+
+/* Define the lock.  */
+__libc_lock_define_initialized (static, syslog_lock)
+
+static void openlog_internal(const char *, int, int) internal_function;
+static void closelog_internal(void);
+#ifndef NO_SIGPIPE
+static void sigpipe_handler (int);
+#endif
+
+#ifndef send_flags
+# define send_flags 0
+#endif
+
+struct cleanup_arg
+{
+  void *buf;
+  struct sigaction *oldaction;
+};
+
+static void
+cancel_handler (void *ptr)
+{
+#ifndef NO_SIGPIPE
+  /* Restore the old signal handler.  */
+  struct cleanup_arg *clarg = (struct cleanup_arg *) ptr;
+
+  if (clarg != NULL && clarg->oldaction != NULL)
+    __sigaction (SIGPIPE, clarg->oldaction, NULL);
+#endif
+
+  /* Free the lock.  */
+  __libc_lock_unlock (syslog_lock);
+}
+
+
+/*
+ * syslog, vsyslog --
+ *	print message on log file; output is intended for syslogd(8).
+ */
+void
+#if __STDC__
+syslog(int pri, const char *fmt, ...)
+#else
+syslog(pri, fmt, va_alist)
+	int pri;
+	char *fmt;
+	va_dcl
+#endif
+{
+	va_list ap;
+
+#if __STDC__
+	va_start(ap, fmt);
+#else
+	va_start(ap);
+#endif
+	vsyslog(pri, fmt, ap);
+	va_end(ap);
+}
+libc_hidden_def (syslog)
+
+void
+vsyslog(pri, fmt, ap)
+	int pri;
+	register const char *fmt;
+	va_list ap;
+{
+	struct tm now_tm;
+	time_t now;
+	int fd;
+	FILE *f;
+	char *buf = 0;
+	size_t bufsize = 0;
+	size_t prioff, msgoff;
+#ifndef NO_SIGPIPE
+ 	struct sigaction action, oldaction;
+ 	int sigpipe;
+#endif
+	int saved_errno = errno;
+	char failbuf[3 * sizeof (pid_t) + sizeof "out of memory []"];
+
+#define	INTERNALLOG	LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
+	/* Check for invalid bits. */
+	if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
+		syslog(INTERNALLOG,
+		    "syslog: unknown facility/priority: %x", pri);
+		pri &= LOG_PRIMASK|LOG_FACMASK;
+	}
+
+	/* Check priority against setlogmask values. */
+	if ((LOG_MASK (LOG_PRI (pri)) & LogMask) == 0)
+		return;
+
+	/* Set default facility if none specified. */
+	if ((pri & LOG_FACMASK) == 0)
+		pri |= LogFacility;
+
+	/* Build the message in a memory-buffer stream.  */
+	f = open_memstream (&buf, &bufsize);
+	if (f == NULL)
+	  {
+	    /* We cannot get a stream.  There is not much we can do but
+	       emitting an error messages.  */
+	    char numbuf[3 * sizeof (pid_t)];
+	    char *nump;
+	    char *endp = __stpcpy (failbuf, "out of memory [");
+	    pid_t pid = __getpid ();
+
+	    nump = numbuf + sizeof (numbuf);
+	    /* The PID can never be zero.  */
+	    do
+	      *--nump = '0' + pid % 10;
+	    while ((pid /= 10) != 0);
+
+	    endp = __mempcpy (endp, nump, (numbuf + sizeof (numbuf)) - nump);
+	    *endp++ = ']';
+	    *endp = '\0';
+	    buf = failbuf;
+	    bufsize = endp - failbuf;
+	    msgoff = 0;
+	  }
+	else
+	  {
+	    __fsetlocking (f, FSETLOCKING_BYCALLER);
+	    prioff = fprintf (f, "<%d>", pri);
+	    (void) time (&now);
+	    f->_IO_write_ptr += __strftime_l (f->_IO_write_ptr,
+					      f->_IO_write_end
+					      - f->_IO_write_ptr,
+					      "%h %e %T ",
+					      __localtime_r (&now, &now_tm),
+					      &_nl_C_locobj);
+	    msgoff = ftell (f);
+	    if (LogTag == NULL)
+	      LogTag = __progname;
+	    if (LogTag != NULL)
+	      fputs_unlocked (LogTag, f);
+	    if (LogStat & LOG_PID)
+	      fprintf (f, "[%d]", (int) __getpid ());
+	    if (LogTag != NULL)
+	      {
+		putc_unlocked (':', f);
+		putc_unlocked (' ', f);
+	      }
+
+	    /* Restore errno for %m format.  */
+	    __set_errno (saved_errno);
+
+	    /* We have the header.  Print the user's format into the
+               buffer.  */
+	    vfprintf (f, fmt, ap);
+
+	    /* Close the memory stream; this will finalize the data
+	       into a malloc'd buffer in BUF.  */
+	    fclose (f);
+	  }
+
+	/* Output to stderr if requested. */
+	if (LogStat & LOG_PERROR) {
+		struct iovec iov[2];
+		register struct iovec *v = iov;
+
+		v->iov_base = buf + msgoff;
+		v->iov_len = bufsize - msgoff;
+		/* Append a newline if necessary.  */
+		if (buf[bufsize - 1] != '\n')
+		  {
+		    ++v;
+		    v->iov_base = (char *) "\n";
+		    v->iov_len = 1;
+		  }
+
+		__libc_cleanup_push (free, buf == failbuf ? NULL : buf);
+
+		/* writev is a cancellation point.  */
+		(void)__writev(STDERR_FILENO, iov, v - iov + 1);
+
+		__libc_cleanup_pop (0);
+	}
+
+	/* Prepare for multiple users.  We have to take care: open and
+	   write are cancellation points.  */
+	struct cleanup_arg clarg;
+	clarg.buf = buf;
+	clarg.oldaction = NULL;
+	__libc_cleanup_push (cancel_handler, &clarg);
+	__libc_lock_lock (syslog_lock);
+
+#ifndef NO_SIGPIPE
+	/* Prepare for a broken connection.  */
+ 	memset (&action, 0, sizeof (action));
+ 	action.sa_handler = sigpipe_handler;
+ 	sigemptyset (&action.sa_mask);
+ 	sigpipe = __sigaction (SIGPIPE, &action, &oldaction);
+	if (sigpipe == 0)
+	  clarg.oldaction = &oldaction;
+#endif
+
+	/* Get connected, output the message to the local logger. */
+	if (!connected)
+		openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
+
+	/* If we have a SOCK_STREAM connection, also send ASCII NUL as
+	   a record terminator.  */
+	if (LogType == SOCK_STREAM)
+	  ++bufsize;
+
+	if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
+	  {
+	    if (connected)
+	      {
+		/* Try to reopen the syslog connection.  Maybe it went
+		   down.  */
+		closelog_internal ();
+		openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
+	      }
+
+	    if (!connected || __send(LogFile, buf, bufsize, send_flags) < 0)
+	      {
+		closelog_internal ();	/* attempt re-open next time */
+		/*
+		 * Output the message to the console; don't worry
+		 * about blocking, if console blocks everything will.
+		 * Make sure the error reported is the one from the
+		 * syslogd failure.
+		 */
+		if (LogStat & LOG_CONS &&
+		    (fd = __open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY, 0)) >= 0)
+		  {
+		    dprintf (fd, "%s\r\n", buf + msgoff);
+		    (void)__close(fd);
+		  }
+	      }
+	  }
+
+#ifndef NO_SIGPIPE
+	if (sigpipe == 0)
+		__sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);
+#endif
+
+	/* End of critical section.  */
+	__libc_cleanup_pop (0);
+	__libc_lock_unlock (syslog_lock);
+
+	if (buf != failbuf)
+		free (buf);
+}
+libc_hidden_def (vsyslog)
+
+static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
+
+
+static void
+internal_function
+openlog_internal(const char *ident, int logstat, int logfac)
+{
+	if (ident != NULL)
+		LogTag = ident;
+	LogStat = logstat;
+	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
+		LogFacility = logfac;
+
+	int retry = 0;
+	while (retry < 2) {
+		if (LogFile == -1) {
+			SyslogAddr.sa_family = AF_UNIX;
+			(void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
+				      sizeof(SyslogAddr.sa_data));
+			if (LogStat & LOG_NDELAY) {
+				if ((LogFile = __socket(AF_UNIX, LogType, 0))
+				    == -1)
+					return;
+				(void)__fcntl(LogFile, F_SETFD, 1);
+			}
+		}
+		if (LogFile != -1 && !connected)
+		{
+			int old_errno = errno;
+			if (__connect(LogFile, &SyslogAddr, sizeof(SyslogAddr))
+			    == -1)
+			{
+				int saved_errno = errno;
+				int fd = LogFile;
+				LogFile = -1;
+				(void)__close(fd);
+				__set_errno (old_errno);
+				if (saved_errno == EPROTOTYPE)
+				{
+					/* retry with the other type: */
+					LogType = (LogType == SOCK_DGRAM
+						   ? SOCK_STREAM : SOCK_DGRAM);
+					++retry;
+					continue;
+				}
+			} else
+				connected = 1;
+		}
+		break;
+	}
+}
+
+void
+openlog (const char *ident, int logstat, int logfac)
+{
+  /* Protect against multiple users and cancellation.  */
+  __libc_cleanup_push (cancel_handler, NULL);
+  __libc_lock_lock (syslog_lock);
+
+  openlog_internal (ident, logstat, logfac);
+
+  __libc_cleanup_pop (1);
+}
+
+#ifndef NO_SIGPIPE
+static void
+sigpipe_handler (int signo)
+{
+  closelog_internal ();
+}
+#endif
+
+static void
+closelog_internal()
+{
+  if (!connected)
+    return;
+
+  __close (LogFile);
+  LogFile = -1;
+  connected = 0;
+}
+
+void
+closelog ()
+{
+  /* Protect against multiple users and cancellation.  */
+  __libc_cleanup_push (cancel_handler, NULL);
+  __libc_lock_lock (syslog_lock);
+
+  closelog_internal ();
+  LogTag = NULL;
+  LogType = SOCK_DGRAM; /* this is the default */
+
+  /* Free the lock.  */
+  __libc_cleanup_pop (1);
+}
+
+/* setlogmask -- set the log mask level */
+int
+setlogmask(pmask)
+	int pmask;
+{
+	int omask;
+
+	omask = LogMask;
+	if (pmask != 0)
+		LogMask = pmask;
+	return (omask);
+}
diff --git a/sysdeps/generic/unsecvars.h b/sysdeps/generic/unsecvars.h
index eb77b260d8..a7378b742f 100644
--- a/sysdeps/generic/unsecvars.h
+++ b/sysdeps/generic/unsecvars.h
@@ -2,18 +2,19 @@
    all stuffed in a single string which means they have to be terminated
    with a '\0' explicitly.  */
 #define UNSECURE_ENVVARS \
-  "LD_PRELOAD\0"							      \
-  "LD_LIBRARY_PATH\0"							      \
-  "LD_ORIGIN_PATH\0"							      \
+  "GCONV_PATH\0"							      \
+  "GETCONF_DIR\0"							      \
+  "HOSTALIASES\0"							      \
+  "LD_AUDIT\0"								      \
   "LD_DEBUG\0"								      \
   "LD_DEBUG_OUTPUT\0"							      \
-  "LD_PROFILE\0"							      \
-  "LD_USE_LOAD_BIAS\0"							      \
   "LD_DYNAMIC_WEAK\0"							      \
+  "LD_LIBRARY_PATH\0"							      \
+  "LD_ORIGIN_PATH\0"							      \
+  "LD_PRELOAD\0"							      \
+  "LD_PROFILE\0"							      \
   "LD_SHOW_AUXV\0"							      \
-  "GCONV_PATH\0"							      \
-  "GETCONF_DIR\0"							      \
-  "HOSTALIASES\0"							      \
+  "LD_USE_LOAD_BIAS\0"							      \
   "LOCALDOMAIN\0"							      \
   "LOCPATH\0"								      \
   "MALLOC_TRACE\0"							      \
diff --git a/sysdeps/generic/wordexp.c b/sysdeps/generic/wordexp.c
index 3e37d6449c..c3d382fb95 100644
--- a/sysdeps/generic/wordexp.c
+++ b/sysdeps/generic/wordexp.c
@@ -1,5 +1,5 @@
 /* POSIX.2 wordexp implementation.
-   Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1997-2002, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Tim Waugh <tim@cyberelk.demon.co.uk>.
 
@@ -810,7 +810,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
 
 /* Function called by child process in exec_comm() */
 static void
-internal_function
+internal_function __attribute__ ((always_inline))
 exec_comm_child (char *comm, int *fildes, int showerr, int noexec)
 {
   const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL };
@@ -868,13 +868,14 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
 	   const char *ifs_white)
 {
   int fildes[2];
-  int bufsize = 128;
+#define bufsize 128
   int buflen;
   int i;
   int status = 0;
   size_t maxnewlines = 0;
-  char *buffer;
+  char buffer[bufsize];
   pid_t pid;
+  int noexec = 0;
 
   /* Don't fork() unless necessary */
   if (!comm || !*comm)
@@ -884,32 +885,42 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
     /* Bad */
     return WRDE_NOSPACE;
 
+ again:
   if ((pid = __fork ()) < 0)
     {
       /* Bad */
-      __close (fildes[0]);
-      __close (fildes[1]);
+      if (fildes[0] != -1)
+	__close (fildes[0]);
+      if (fildes[1] != -1)
+	__close (fildes[1]);
       return WRDE_NOSPACE;
     }
 
   if (pid == 0)
-    exec_comm_child (comm, fildes, flags & WRDE_SHOWERR, 0);
+    exec_comm_child (comm, fildes, noexec ? 0 : flags & WRDE_SHOWERR, noexec);
 
   /* Parent */
 
+  /* If we are just testing the syntax, only wait.  */
+  if (noexec)
+    return (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) == pid
+	    && status != 0) ? WRDE_SYNTAX : 0;
+
   __close (fildes[1]);
-  buffer = __alloca (bufsize);
+  fildes[1] = -1;
 
   if (!pwordexp)
     /* Quoted - no field splitting */
     {
       while (1)
 	{
-	  if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+	  if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+						    bufsize))) < 1)
 	    {
-	      if (__waitpid (pid, &status, WNOHANG) == 0)
+	      if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, WNOHANG)) == 0)
 		continue;
-	      if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+	      if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+							bufsize))) < 1)
 		break;
 	    }
 
@@ -933,11 +944,13 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
 
       while (1)
 	{
-	  if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+	  if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+						    bufsize))) < 1)
 	    {
-	      if (__waitpid (pid, &status, WNOHANG) == 0)
+	      if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, WNOHANG)) == 0)
 		continue;
-	      if ((buflen = __read (fildes[0], buffer, bufsize)) < 1)
+	      if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
+							bufsize))) < 1)
 		break;
 	    }
 
@@ -1053,31 +1066,20 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length,
     }
 
   __close (fildes[0]);
+  fildes[0] = -1;
 
   /* Check for syntax error (re-execute but with "-n" flag) */
   if (buflen < 1 && status != 0)
     {
-      if ((pid = __fork ()) < 0)
-	{
-	  /* Bad */
-	  return WRDE_NOSPACE;
-	}
-
-      if (pid == 0)
-	{
-          fildes[0] = fildes[1] = -1;
-	  exec_comm_child (comm, fildes, 0, 1);
-	}
-
-      if (__waitpid (pid, &status, 0) == pid && status != 0)
-	return WRDE_SYNTAX;
+      noexec = 1;
+      goto again;
     }
 
   return 0;
 
 no_space:
   __kill (pid, SIGKILL);
-  __waitpid (pid, NULL, 0);
+  TEMP_FAILURE_RETRY (__waitpid (pid, NULL, 0));
   __close (fildes[0]);
   return WRDE_NOSPACE;
 }
diff --git a/sysdeps/hppa/bits/link.h b/sysdeps/hppa/bits/link.h
index 54842b2299..e69de29bb2 100644
--- a/sysdeps/hppa/bits/link.h
+++ b/sysdeps/hppa/bits/link.h
@@ -1,6 +0,0 @@
-/* Used to store the function descriptor table */
-struct link_map_machine
-  {
-    size_t fptr_table_len;
-    ElfW(Addr) *fptr_table;
-  };
diff --git a/sysdeps/hppa/bits/linkmap.h b/sysdeps/hppa/bits/linkmap.h
new file mode 100644
index 0000000000..54842b2299
--- /dev/null
+++ b/sysdeps/hppa/bits/linkmap.h
@@ -0,0 +1,6 @@
+/* Used to store the function descriptor table */
+struct link_map_machine
+  {
+    size_t fptr_table_len;
+    ElfW(Addr) *fptr_table;
+  };
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h
index d393b3e427..84436e7c56 100644
--- a/sysdeps/hppa/dl-lookupcfg.h
+++ b/sysdeps/hppa/dl-lookupcfg.h
@@ -1,5 +1,5 @@
 /* Configuration of lookup functions.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2004 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
@@ -17,9 +17,6 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-/* Like IA-64, PA-RISC needs more information from the symbol lookup
-   function than just the address. */
-#define DL_LOOKUP_RETURNS_MAP
 #define ELF_FUNCTION_PTR_IS_SPECIAL
 #define DL_UNMAP_IS_SPECIAL
 
@@ -66,4 +63,3 @@ void _dl_unmap (struct link_map *map);
   ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
 #define DL_DT_FINI_ADDRESS(map, addr) \
   ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))
-
diff --git a/sysdeps/i386/Makefile b/sysdeps/i386/Makefile
index 52faaa3109..ece94f3610 100644
--- a/sysdeps/i386/Makefile
+++ b/sysdeps/i386/Makefile
@@ -61,3 +61,7 @@ CFLAGS-dlopenold.c += -mpreferred-stack-boundary=4
 CFLAGS-dlclose.c += -mpreferred-stack-boundary=4
 CFLAGS-dlerror.c += -mpreferred-stack-boundary=4
 endif
+
+ifneq (,$(filter -mno-tls-direct-seg-refs,$(CFLAGS)))
+defines += -DNO_TLS_DIRECT_SEG_REFS
+endif
diff --git a/sysdeps/i386/bits/link.h b/sysdeps/i386/bits/link.h
index 3be9b7eae8..985d040413 100644
--- a/sysdeps/i386/bits/link.h
+++ b/sysdeps/i386/bits/link.h
@@ -1,5 +1,60 @@
-struct link_map_machine
-  {
-    Elf32_Addr plt; /* Address of .plt + 0x16 */
-    Elf32_Addr gotplt; /* Address of .got + 0x0c */
-  };
+/* Copyright (C) 2004, 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on IA-32.  */
+typedef struct La_i86_regs
+{
+  uint32_t lr_edx;
+  uint32_t lr_ecx;
+  uint32_t lr_eax;
+  uint32_t lr_ebp;
+  uint32_t lr_esp;
+} La_i86_regs;
+
+/* Return values for calls from PLT on IA-32.  */
+typedef struct La_i86_retval
+{
+  uint32_t lrv_eax;
+  uint32_t lrv_edx;
+  long double lrv_st0;
+  long double lrv_st1;
+} La_i86_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_i86_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+				       uintptr_t *__refcook,
+				       uintptr_t *__defcook,
+				       La_i86_regs *__regs,
+				       unsigned int *__flags,
+				       const char *__symname,
+				       long int *__framesizep);
+extern unsigned int la_i86_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+					uintptr_t *__refcook,
+					uintptr_t *__defcook,
+					const La_i86_regs *__inregs,
+					La_i86_retval *__outregs,
+					const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/i386/bits/linkmap.h b/sysdeps/i386/bits/linkmap.h
new file mode 100644
index 0000000000..3be9b7eae8
--- /dev/null
+++ b/sysdeps/i386/bits/linkmap.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt + 0x16 */
+    Elf32_Addr gotplt; /* Address of .got + 0x0c */
+  };
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index c48d9d325e..78c083f6ab 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  i386 version.
-   Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1995-2002, 2003, 2004, 2005 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
@@ -129,7 +129,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	{
 	  got[2] = (Elf32_Addr) &_dl_runtime_profile;
 
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = l;
@@ -154,112 +155,18 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
    destroys the passed register information.  */
 /* GKM FIXME: Fix trampoline to pass bounds so we can do
    without the `__unbounded' qualifier.  */
-#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), unused))
+#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused))
 
-static ElfW(Addr) fixup (struct link_map *__unbounded l,
-			 ElfW(Word) reloc_offset)
+extern ElfW(Addr) _dl_fixup (struct link_map *__unbounded l,
+			     ElfW(Word) reloc_offset)
      ARCH_FIXUP_ATTRIBUTE;
-static ElfW(Addr) profile_fixup (struct link_map *l, ElfW(Word) reloc_offset,
-				 ElfW(Addr) retaddr)
+extern ElfW(Addr) _dl_profile_fixup (struct link_map *l,
+				     ElfW(Word) reloc_offset,
+				     ElfW(Addr) retaddr, void *regs,
+				     long int *framesizep)
      ARCH_FIXUP_ATTRIBUTE;
 # endif
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-# if !defined PROF && !__BOUNDED_POINTERS__
-#  define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
-	.text\n\
-	.globl _dl_runtime_resolve\n\
-	.type _dl_runtime_resolve, @function\n\
-	" CFI_STARTPROC "\n\
-	.align 16\n\
-_dl_runtime_resolve:\n\
-	" CFI_ADJUST_CFA_OFFSET (8) "\n\
-	pushl %eax		# Preserve registers otherwise clobbered.\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	pushl %ecx\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	pushl %edx\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	movl 16(%esp), %edx	# Copy args pushed by PLT in register.  Note\n\
-	movl 12(%esp), %eax	# that `fixup' takes its parameters in regs.\n\
-	call fixup		# Call resolver.\n\
-	popl %edx		# Get register content back.\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	popl %ecx\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	xchgl %eax, (%esp)	# Get %eax contents end store function address.\n\
-	ret $8			# Jump to function address.\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
-	.globl _dl_runtime_profile\n\
-	.type _dl_runtime_profile, @function\n\
-	" CFI_STARTPROC "\n\
-	.align 16\n\
-_dl_runtime_profile:\n\
-	" CFI_ADJUST_CFA_OFFSET (8) "\n\
-	pushl %eax		# Preserve registers otherwise clobbered.\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	pushl %ecx\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	pushl %edx\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	movl 20(%esp), %ecx	# Load return address\n\
-	movl 16(%esp), %edx	# Copy args pushed by PLT in register.  Note\n\
-	movl 12(%esp), %eax	# that `fixup' takes its parameters in regs.\n\
-	call profile_fixup	# Call resolver.\n\
-	popl %edx		# Get register content back.\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	popl %ecx\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	xchgl %eax, (%esp)	# Get %eax contents end store function address.\n\
-	ret $8			# Jump to function address.\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_profile, .-_dl_runtime_profile\n\
-	.previous\n\
-");
-# else
-#  define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
-	.text\n\
-	.globl _dl_runtime_resolve\n\
-	.globl _dl_runtime_profile\n\
-	.type _dl_runtime_resolve, @function\n\
-	.type _dl_runtime_profile, @function\n\
-	" CFI_STARTPROC "\n\
-	.align 16\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
-	" CFI_ADJUST_CFA_OFFSET (8) "\n\
-	pushl %eax		# Preserve registers otherwise clobbered.\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	pushl %ecx\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	pushl %edx\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	movl 16(%esp), %edx	# Push the arguments for `fixup'\n\
-	movl 12(%esp), %eax\n\
-	pushl %edx\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	pushl %eax\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	call fixup		# Call resolver.\n\
-	popl %edx		# Pop the parameters\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	popl %ecx\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	popl %edx		# Get register content back.\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	popl %ecx\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	xchgl %eax, (%esp)	# Get %eax contents end store function address.\n\
-	ret $8			# Jump to function address.\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-	.size _dl_runtime_profile, .-_dl_runtime_profile\n\
-	.previous\n\
-");
-# endif
 #endif
 
 /* Mask identifying addresses reserved for the user program,
@@ -308,11 +215,21 @@ _dl_start_user:\n\
 	movl _rtld_local@GOTOFF(%ebx), %eax\n\
 	leal 8(%esp,%edx,4), %esi\n\
 	leal 4(%esp), %ecx\n\
+	movl %esp, %ebp\n\
+	# Make sure _dl_init is run with 16 byte aligned stack.\n\
+	andl $-16, %esp\n\
+	pushl %eax\n\
+	pushl %eax\n\
+	pushl %ebp\n\
 	pushl %esi\n\
+	# Clear %ebp, so that even constructors have terminated backchain.\n\
+	xorl %ebp, %ebp\n\
 	# Call the function to run the initializers.\n\
 	call _dl_init_internal@PLT\n\
 	# Pass our finalizer function to the user in %edx, as per ELF ABI.\n\
 	leal _dl_fini@GOTOFF(%ebx), %edx\n\
+	# Restore %esp _start expects.\n\
+	movl (%esp), %esp\n\
 	# Jump to the user's entry point.\n\
 	jmp *%edi\n\
 	.previous\n\
@@ -375,9 +292,14 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rel *reloc,
   return value;
 }
 
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER i86_gnu_pltenter
+#define ARCH_LA_PLTEXIT i86_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* The i386 never uses Elf32_Rela relocations for the dynamic linker.
    Prelinked libraries may use Elf32_Rela though.  */
@@ -422,17 +344,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 #endif	/* !RTLD_BOOTSTRAP and have no -z combreloc */
     {
       const Elf32_Sym *const refsym = sym;
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
-      Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
-      Elf32_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
-      if (sym != NULL)
-# endif
-	value += sym->st_value;
-#endif	/* use TLS and !RTLD_BOOTSTRAP */
+      Elf32_Addr value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
 
       switch (r_type)
 	{
@@ -549,14 +462,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 # ifndef RESOLVE_CONFLICT_FIND_MAP
       const Elf32_Sym *const refsym = sym;
 # endif
-# ifdef USE_TLS
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-# else
-      Elf32_Addr value = RESOLVE (&sym, version, r_type);
-      if (sym != NULL)
-	value += sym->st_value;
-# endif
 
       switch (ELF32_R_TYPE (reloc->r_info))
 	{
@@ -692,4 +599,4 @@ elf_machine_lazy_rela (struct link_map *map,
 
 #endif	/* !RTLD_BOOTSTRAP */
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S
new file mode 100644
index 0000000000..80dd300e86
--- /dev/null
+++ b/sysdeps/i386/dl-trampoline.S
@@ -0,0 +1,182 @@
+/* PLT trampolines.  i386 version.
+   Copyright (C) 2004, 2005 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 <sysdep.h>
+
+	.text
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_resolve:
+	cfi_adjust_cfa_offset (8)
+	pushl %eax		# Preserve registers otherwise clobbered.
+	cfi_adjust_cfa_offset (4)
+	pushl %ecx
+	cfi_adjust_cfa_offset (4)
+	pushl %edx
+	cfi_adjust_cfa_offset (4)
+	movl 16(%esp), %edx	# Copy args pushed by PLT in register.  Note
+	movl 12(%esp), %eax	# that `fixup' takes its parameters in regs.
+	call _dl_fixup		# Call resolver.
+	popl %edx		# Get register content back.
+	cfi_adjust_cfa_offset (-4)
+	popl %ecx
+	cfi_adjust_cfa_offset (-4)
+	xchgl %eax, (%esp)	# Get %eax contents end store function address.
+	ret $8			# Jump to function address.
+	cfi_endproc
+	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_profile:
+	cfi_adjust_cfa_offset (8)
+	pushl %esp
+	cfi_adjust_cfa_offset (4)
+	addl $8, (%esp)		# Account for the pushed PLT data
+	pushl %ebp
+	cfi_adjust_cfa_offset (4)
+	pushl %eax		# Preserve registers otherwise clobbered.
+	cfi_adjust_cfa_offset (4)
+	pushl %ecx
+	cfi_adjust_cfa_offset (4)
+	pushl %edx
+	cfi_adjust_cfa_offset (4)
+	movl %esp, %ecx
+	subl $8, %esp
+	cfi_adjust_cfa_offset (8)
+	movl $-1, 4(%esp)
+	leal 4(%esp), %edx
+	movl %edx, (%esp)
+	pushl %ecx		# Address of the register structure
+	cfi_adjust_cfa_offset (4)
+	movl 40(%esp), %ecx	# Load return address
+	movl 36(%esp), %edx	# Copy args pushed by PLT in register.  Note
+	movl 32(%esp), %eax	# that `fixup' takes its parameters in regs.
+	call _dl_profile_fixup	# Call resolver.
+	cfi_adjust_cfa_offset (-8)
+	movl (%esp), %edx
+	testl %edx, %edx
+	jns 1f
+	popl %edx
+	cfi_adjust_cfa_offset (-4)
+	popl %edx		# Get register content back.
+	cfi_adjust_cfa_offset (-4)
+	popl %ecx
+	cfi_adjust_cfa_offset (-4)
+	xchgl %eax, (%esp)	# Get %eax contents end store function address.
+	ret $16			# Jump to function address.
+
+	/*
+	    +32     return address
+	    +28     PLT1
+	    +24     PLT2
+	    +20     %esp
+	    +16     %ebp
+	    +12     %eax
+	    +8      %ecx
+	    +4      %edx
+	   %esp     free
+	*/
+	cfi_adjust_cfa_offset (12)
+1:	movl %ebx, (%esp)
+	cfi_rel_offset (3, 0)
+	movl %edx, %ebx		# This is the frame buffer size
+	pushl %edi
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (7, 0)
+	pushl %esi
+	cfi_adjust_cfa_offset (4)
+	cfi_rel_offset (6, 0)
+	leal 44(%esp), %esi
+	movl %ebx, %ecx
+	movl %esp, %edi
+	subl %ebx, %edi
+	andl $0xfffffff0, %edi	# Align stack
+	movl %esp, %ebx
+	cfi_def_cfa_register (3)
+	movl %edi, %esp
+	shrl $2, %ecx
+	rep
+	movsl
+	movl (%edi), %esi
+	cfi_restore (6)
+	movl 4(%edi), %edi
+	cfi_restore (7)
+	/*
+	   %ebx+40  return address
+	   %ebx+36  PLT1
+	   %ebx+32  PLT2
+	   %ebx+28  %esp
+	   %ebx+24  %ebp
+	   %ebx+20  %eax
+	   %ebx+16  %ecx
+	   %ebx+12  %edx
+	   %ebx+8   %ebx
+	   %ebx+4   free
+	   %ebx     free
+	   %esp     copied stack frame
+	*/
+	movl %eax, (%ebx)
+	movl 12(%ebx), %edx
+	movl 16(%ebx), %ecx
+	movl 20(%ebx), %eax
+	call *(%ebx)
+	movl %ebx, %esp
+	cfi_def_cfa_register (4)
+	movl 8(%esp), %ebx
+	cfi_restore (3)
+	/*
+	    +40     return address
+	    +36     PLT1
+	    +32     PLT2
+	    +28     %esp
+	    +24     %ebp
+	    +20     %eax
+	    +16     %ecx
+	    +12     %edx
+	    +8      free
+	    +4      free
+	   %esp     free
+	*/
+	subl $20, %esp
+	cfi_adjust_cfa_offset (20)
+	movl %eax, (%esp)
+	movl %edx, 4(%esp)
+	fstpt 8(%esp)
+	fstpt 20(%esp)
+	pushl %esp
+	cfi_adjust_cfa_offset (4)
+	leal 36(%esp), %ecx
+	movl 56(%esp), %eax
+	movl 60(%esp), %edx
+	call _dl_call_pltexit
+	movl (%esp), %eax
+	movl 4(%esp), %edx
+	fldt 20(%esp)
+	fldt 8(%esp)
+	addl $60, %esp
+	cfi_adjust_cfa_offset (-60)
+	ret
+	cfi_endproc
+	.size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/ia64/bits/link.h b/sysdeps/ia64/bits/link.h
index 7f8b0550d9..f751c23fd1 100644
--- a/sysdeps/ia64/bits/link.h
+++ b/sysdeps/ia64/bits/link.h
@@ -1,5 +1,63 @@
-struct link_map_machine
-  {
-    size_t fptr_table_len;
-    Elf64_Addr *fptr_table;
-  };
+/* Copyright (C) 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+/* Registers for entry into PLT on ia64.  */
+typedef struct La_ia64_regs
+{
+  uint64_t lr_r8;
+  uint64_t lr_r9;
+  uint64_t lr_r10;
+  uint64_t lr_r11;
+  uint64_t lr_gr [8];
+  long double lr_fr [8];
+  uint64_t lr_unat;
+  uint64_t lr_sp;
+} La_ia64_regs;
+
+/* Return values for calls from PLT on ia64.  */
+typedef struct La_ia64_retval
+{
+  uint64_t lrv_r8;
+  uint64_t lrv_r9;
+  uint64_t lrv_r10;
+  uint64_t lrv_r11;
+  long double lr_fr [8];
+} La_ia64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_ia64_gnu_pltenter (Elf64_Sym *__sym, unsigned int __ndx,
+				       uintptr_t *__refcook,
+				       uintptr_t *__defcook,
+				       La_ia64_regs *__regs,
+				       unsigned int *__flags,
+				       const char *__symname,
+				       long int *__framesizep);
+extern unsigned int la_ia64_gnu_pltexit (Elf64_Sym *__sym, unsigned int __ndx,
+					uintptr_t *__refcook,
+					uintptr_t *__defcook,
+					const La_ia64_regs *__inregs,
+					La_ia64_retval *__outregs,
+					const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/ia64/bits/linkmap.h b/sysdeps/ia64/bits/linkmap.h
new file mode 100644
index 0000000000..7f8b0550d9
--- /dev/null
+++ b/sysdeps/ia64/bits/linkmap.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+  {
+    size_t fptr_table_len;
+    Elf64_Addr *fptr_table;
+  };
diff --git a/sysdeps/ia64/dl-lookupcfg.h b/sysdeps/ia64/dl-lookupcfg.h
index 0ae3dd68ba..b50030ebd2 100644
--- a/sysdeps/ia64/dl-lookupcfg.h
+++ b/sysdeps/ia64/dl-lookupcfg.h
@@ -1,5 +1,5 @@
 /* Configuration of lookup functions.
-   Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2003, 2004 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
@@ -17,12 +17,11 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-/* The ia64 need more information from the symbol lookup function
-   than just the address. */
-#define DL_LOOKUP_RETURNS_MAP
 #define ELF_FUNCTION_PTR_IS_SPECIAL
 #define DL_UNMAP_IS_SPECIAL
 
+#include <dl-fptr.h>
+
 /* We do not support copy relocations for IA-64.  */
 #define DL_NO_COPY_RELOCS
 
@@ -59,3 +58,15 @@ extern void _dl_unmap (struct link_map *map);
 
 #define DL_DT_INIT_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr)
 #define DL_DT_FINI_ADDRESS(map, addr) DL_AUTO_FUNCTION_ADDRESS (map, addr)
+/* The type of the return value of fixup/profile_fixup.  */
+#define DL_FIXUP_VALUE_TYPE struct fdesc
+/* Construct a value of type DL_FIXUP_VALUE_TYPE from a code address
+   and a link map.  */
+#define DL_FIXUP_MAKE_VALUE(map, addr) \
+  ((struct fdesc) { (addr), (map)->l_info[DT_PLTGOT]->d_un.d_ptr })
+/* Extract the code address from a value of type DL_FIXUP_MAKE_VALUE.
+ */
+#define DL_FIXUP_VALUE_CODE_ADDR(value) (value).ip
+
+#define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
+#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h
index 3108047869..55349690e3 100644
--- a/sysdeps/ia64/dl-machine.h
+++ b/sysdeps/ia64/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  IA-64 version.
-   Copyright (C) 1995-1997, 2000-2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1995-1997, 2000-2004, 2005 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
@@ -123,7 +123,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	doit = (Elf64_Addr) ((struct fdesc *) &_dl_runtime_resolve)->ip;
       else
 	{
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    {
 	      /* This is the object we are looking for.  Say that we really
 		 want profiling and the timers are started.  */
@@ -139,133 +140,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-
-/*
-   This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns. `fixup()' takes two
-   arguments, however profile_fixup() takes three.
-
-   The ABI specifies that we will never see more than 8 input
-   registers to a function call, thus it is safe to simply allocate
-   those, and simpler than playing stack games.
-					                     - 12/09/99 Jes
- */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name)			     \
-  extern void tramp_name (void);					     \
-  asm (									     \
-"	.global " #tramp_name "#\n"					     \
-"	.proc " #tramp_name "#\n"					     \
-#tramp_name ":\n"							     \
-"	{ .mmi\n"							     \
-"	  .prologue\n"							     \
-"	  .save ar.pfs, r40\n"						     \
-"	  alloc loc0 = ar.pfs, 8, 6, 3, 0\n"				     \
-"	  adds r2 = -144, r12\n"					     \
-"	  adds r3 = -128, r12\n"					     \
-"	}\n"								     \
-"	{ .mii\n"							     \
-"	  .fframe 160\n"						     \
-"	  adds r12 = -160, r12\n"					     \
-"	  .save rp, r41\n"						     \
-"	  mov loc1 = b0\n"						     \
-"	  .body\n"							     \
-"	  mov out2 = b0		/* needed by fixup_profile */\n"	     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mfb\n"							     \
-"	  mov loc2 = r8		/* preserve struct value register */\n"	     \
-"	  nop.f 0\n"							     \
-"	  nop.b 0\n"							     \
-"	}\n"								     \
-"	{ .mii\n"							     \
-"	  mov loc3 = r9		/* preserve language specific register */\n" \
-"	  mov loc4 = r10	/* preserve language specific register */\n" \
-"	  mov loc5 = r11	/* preserve language specific register */\n" \
-"	}\n"								     \
-"	{ .mmi\n"							     \
-"	  stf.spill [r2] = f8, 32\n"					     \
-"	  stf.spill [r3] = f9, 32\n"					     \
-"	  mov out0 = r16\n"						     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mmi\n"							     \
-"	  stf.spill [r2] = f10, 32\n"					     \
-"	  stf.spill [r3] = f11, 32\n"					     \
-"	  shl out1 = r15, 4\n"						     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mmi\n"							     \
-"	  stf.spill [r2] = f12, 32\n"					     \
-"	  stf.spill [r3] = f13, 32\n"					     \
-"	  shladd out1 = r15, 3, out1\n"					     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mmb\n"							     \
-"	  stf.spill [r2] = f14\n"					     \
-"	  stf.spill [r3] = f15\n"					     \
-"	  br.call.sptk.many b0 = " #fixup_name "#\n"			     \
-"	}\n"								     \
-"	{ .mii\n"							     \
-"	  ld8 r9 = [ret0], 8\n"						     \
-"	  adds r2 = 16, r12\n"						     \
-"	  adds r3 = 32, r12\n"						     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mmi\n"							     \
-"	  ldf.fill f8 = [r2], 32\n"					     \
-"	  ldf.fill f9 = [r3], 32\n"					     \
-"	  mov b0 = loc1\n"						     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mmi\n"							     \
-"	  ldf.fill f10 = [r2], 32\n"					     \
-"	  ldf.fill f11 = [r3], 32\n"					     \
-"	  mov b6 = r9\n"						     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mmi\n"							     \
-"	  ldf.fill f12 = [r2], 32\n"					     \
-"	  ldf.fill f13 = [r3], 32\n"					     \
-"	  mov ar.pfs = loc0\n"						     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mmi\n"							     \
-"	  ldf.fill f14 = [r2], 32\n"					     \
-"	  ldf.fill f15 = [r3], 32\n"					     \
-"	  .restore sp		/* pop the unwind frame state */\n"	     \
-"	  adds r12 = 160, r12\n"					     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	{ .mii\n"							     \
-"	  mov r9 = loc3		/* restore language specific register */\n"  \
-"	  mov r10 = loc4	/* restore language specific register */\n"  \
-"	  mov r11 = loc5	/* restore language specific register */\n"  \
-"	}\n"								     \
-"	{ .mii\n"							     \
-"	  ld8 gp = [ret0]\n"						     \
-"	  mov r8 = loc2		/* restore struct value register */\n"	     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	/* An alloc is needed for the break system call to work.\n"	     \
-"	   We don't care about the old value of the pfs register.  */\n"     \
-"	{ .mmb\n"							     \
-"	  .prologue\n"							     \
-"	  .body\n"							     \
-"	  alloc r2 = ar.pfs, 0, 0, 8, 0\n"				     \
-"	  br.sptk.many b6\n"						     \
-"	  ;;\n"								     \
-"	}\n"								     \
-"	.endp " #tramp_name "#\n");
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE 				\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);		\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE				\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);		\
-  strong_alias (_dl_runtime_resolve, _dl_runtime_profile);
-#endif
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER ia64_gnu_pltenter
+#define ARCH_LA_PLTEXIT ia64_gnu_pltexit
 
 /* Undo the adds out0 = 16, sp below to get at the value we want in
    __libc_stack_end.  */
@@ -454,34 +331,29 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 #define ELF_MACHINE_START_ADDRESS(map, start)	\
   DL_STATIC_FUNCTION_ADDRESS (map, start)
 
-#define elf_machine_profile_fixup_plt(l, reloc, rel_addr, value) \
-  elf_machine_fixup_plt (l, reloc, rel_addr, value)
-
-#define elf_machine_profile_plt(reloc_addr) ((Elf64_Addr) (reloc_addr))
-
 /* Fixup a PLT entry to bounce directly to the function at VALUE.  */
-static inline Elf64_Addr __attribute__ ((always_inline))
+static inline struct fdesc __attribute__ ((always_inline))
 elf_machine_fixup_plt (struct link_map *l, lookup_t t,
 		       const Elf64_Rela *reloc,
-		       Elf64_Addr *reloc_addr, Elf64_Addr value)
+		       Elf64_Addr *reloc_addr, struct fdesc value)
 {
   /* l is the link_map for the caller, t is the link_map for the object
    * being called */
   /* got has already been relocated in elf_get_dynamic_info() */
-  reloc_addr[1] = t->l_info[DT_PLTGOT]->d_un.d_ptr;
+  reloc_addr[1] = value.gp;
   /* we need a "release" here to ensure that the gp is visible before
      the code entry point is updated: */
-  ((volatile Elf64_Addr *) reloc_addr)[0] = value;
-  return (Elf64_Addr) reloc_addr;
+  ((volatile Elf64_Addr *) reloc_addr)[0] = value.ip;
+  return value;
 }
 
 /* Return the final value of a plt relocation.  */
-static inline Elf64_Addr
+static inline struct fdesc
 elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
-		       Elf64_Addr value)
+		       struct fdesc value)
 {
   /* No need to handle rel vs rela since IA64 is rela only */
-  return value + reloc->r_addend;
+  return (struct fdesc) { value.ip + reloc->r_addend, value.gp };
 }
 
 #endif /* !dl_machine_h */
@@ -552,7 +424,8 @@ elf_machine_rela (struct link_map *map,
 	    ;/* No adjustment.  */
 	  else if (r_type == R_IA64_IPLTLSB)
 	    {
-	      elf_machine_fixup_plt (NULL, sym_map, reloc, reloc_addr, value);
+	      elf_machine_fixup_plt (NULL, NULL, reloc, reloc_addr,
+				     DL_FIXUP_MAKE_VALUE (sym_map, value));
 	      return;
 	    }
 	  else if (R_IA64_TYPE (r_type) == R_IA64_TYPE (R_IA64_FPTR64LSB))
diff --git a/sysdeps/ia64/dl-trampoline.S b/sysdeps/ia64/dl-trampoline.S
new file mode 100644
index 0000000000..b7969a6cf0
--- /dev/null
+++ b/sysdeps/ia64/dl-trampoline.S
@@ -0,0 +1,537 @@
+/* PLT trampolines.  ia64 version.
+   Copyright (C) 2005 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 <sysdep.h>
+#undef ret
+
+/*
+   This code is used in dl-runtime.c to call the `_dl_fixup' function
+   and then redirect to the address it returns. `_dl_fixup()' takes two
+   arguments, however _dl_profile_fixup() takes five.
+
+   The ABI specifies that we will never see more than 8 input
+   registers to a function call, thus it is safe to simply allocate
+   those, and simpler than playing stack games.  */
+
+/* Used to save and restore 8 incoming fp registers */
+#define RESOLVE_FRAME_SIZE (16*8)
+
+ENTRY(_dl_runtime_resolve)
+	{ .mmi
+	  .prologue
+	  .save ar.pfs, r40
+	  alloc loc0 = ar.pfs, 8, 6, 2, 0
+	  /* Use the 16 byte scratch area. r2 will start at f8 and
+	     r3 will start at f9.  */
+	  adds r2 = -(RESOLVE_FRAME_SIZE - 16), r12
+	  adds r3 = -(RESOLVE_FRAME_SIZE - 32), r12
+	}
+	{ .mii
+	  .fframe RESOLVE_FRAME_SIZE
+	  adds r12 = -RESOLVE_FRAME_SIZE, r12
+	  .save rp, loc1
+	  mov loc1 = b0
+	  .body
+	  mov loc2 = r8		/* preserve struct value register */
+	  ;;
+	}
+	{ .mii
+	  mov loc3 = r9		/* preserve language specific register */
+	  mov loc4 = r10	/* preserve language specific register */
+	  mov loc5 = r11	/* preserve language specific register */
+	}
+	{ .mmi
+	  stf.spill [r2] = f8, 32
+	  stf.spill [r3] = f9, 32
+	  mov out0 = r16
+	  ;;
+	}
+	{ .mmi
+	  stf.spill [r2] = f10, 32
+	  stf.spill [r3] = f11, 32
+	  shl out1 = r15, 4
+	  ;;
+	}
+	{ .mmi
+	  stf.spill [r2] = f12, 32
+	  stf.spill [r3] = f13, 32
+	  /* Relocation record is 24 byte. */
+	  shladd out1 = r15, 3, out1
+	  ;;
+	}
+	{ .mmb
+	  stf.spill [r2] = f14
+	  stf.spill [r3] = f15
+	  br.call.sptk.many b0 = _dl_fixup
+	}
+	{ .mii
+	  /* Skip the 16byte scratch area.  */
+	  adds r2 = 16, r12
+	  adds r3 = 32, r12
+	  mov b6 = ret0
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f8 = [r2], 32
+	  ldf.fill f9 = [r3], 32
+	  mov b0 = loc1
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f10 = [r2], 32
+	  ldf.fill f11 = [r3], 32
+	  mov gp = ret1
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f12 = [r2], 32
+	  ldf.fill f13 = [r3], 32
+	  mov ar.pfs = loc0
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f14 = [r2], 32
+	  ldf.fill f15 = [r3], 32
+	  .restore sp		/* pop the unwind frame state */
+	  adds r12 = RESOLVE_FRAME_SIZE, r12
+	  ;;
+	}
+	{ .mii
+	  mov r9 = loc3		/* restore language specific register */
+	  mov r10 = loc4	/* restore language specific register */
+	  mov r11 = loc5	/* restore language specific register */
+	}
+	{ .mii
+	  mov r8 = loc2		/* restore struct value register */
+	  ;;
+	}
+	/* An alloc is needed for the break system call to work.
+	   We don't care about the old value of the pfs register.  */
+	{ .mmb
+	  .prologue
+	  .body
+	  alloc r2 = ar.pfs, 0, 0, 8, 0
+	  br.sptk.many b6
+	  ;;
+	}
+END(_dl_runtime_resolve)
+
+
+/* The fourth argument to _dl_profile_fixup and the third one to
+   _dl_call_pltexit are a pointer to La_ia64_regs:
+
+   8byte r8
+   8byte r9
+   8byte r10
+   8byte r11
+   8byte in0
+   8byte in1
+   8byte in2
+   8byte in3
+   8byte in4
+   8byte in5
+   8byte in6
+   8byte in7
+   16byte f8
+   16byte f9
+   16byte f10
+   16byte f11
+   16byte f12
+   16byte f13
+   16byte f14
+   16byte f15
+   8byte ar.unat
+   8byte sp
+
+   The fifth argument to _dl_profile_fixup is a pointer to long int.
+   The fourth argument to _dl_call_pltexit is a pointer to
+   La_ia64_retval:
+
+   8byte r8
+   8byte r9
+   8byte r10
+   8byte r11
+   16byte f8
+   16byte f9
+   16byte f10
+   16byte f11
+   16byte f12
+   16byte f13
+   16byte f14
+   16byte f15
+  
+  Since stack has to be 16 byte aligned, the stack allocation is in
+  16byte increment. Before calling _dl_profile_fixup, the stack will
+  look like
+
+  psp	new frame_size
+  +16	La_ia64_regs
+  sp	scratch
+
+ */
+
+#define PLTENTER_FRAME_SIZE (4*8 + 8*8 + 8*16 + 2*8 + 16)
+#define PLTEXIT_FRAME_SIZE (PLTENTER_FRAME_SIZE + 4*8 + 8*16)
+
+ENTRY(_dl_runtime_profile)
+	{ .mii
+	  .prologue
+	  .save ar.pfs, r40
+	  alloc loc0 = ar.pfs, 8, 12, 8, 0
+	  .vframe loc10
+	  mov loc10 = r12
+	  .save rp, loc1
+	  mov loc1 = b0
+	}
+	{ .mii
+	  .save ar.unat, r17
+	  mov r17 = ar.unat
+	  .save ar.lc, loc6
+	  mov loc6 = ar.lc
+	  mov loc11 = gp
+	}
+	{ .mii
+	  .body
+	  /* There is a 16 byte scratch area. r2 will start at r8 and
+	     r3 will start at r9 for La_ia64_regs.  */
+	  adds r2 = -(PLTENTER_FRAME_SIZE - 16), r12
+	  adds r3 = -(PLTENTER_FRAME_SIZE - 24), r12
+	  adds r12 = -PLTENTER_FRAME_SIZE, r12
+	  ;;
+	}
+	{ .mmi
+	  st8 [r2] = r8, 16;
+	  st8 [r3] = r9, 16;
+	  mov out2 = b0		/* needed by _dl_fixup_profile */
+	  ;;
+	}
+	{ .mmi
+	  st8 [r2] = r10, 16;
+	  st8 [r3] = r11, 16;
+	  adds out3 = 16, r12	/* pointer to La_ia64_regs */
+	  ;;
+	}
+	{ .mmi
+	  .mem.offset 0, 0
+	  st8.spill [r2] = in0, 16
+	  .mem.offset 8, 0
+	  st8.spill [r3] = in1, 16
+	  mov out4 = loc10	/* pointer to new frame size  */
+	  ;;
+	}
+	{ .mmi
+	  .mem.offset 0, 0
+	  st8.spill [r2] = in2, 16
+	  .mem.offset 8, 0
+	  st8.spill [r3] = in3, 16
+	  mov loc2 = r8		/* preserve struct value register */
+	  ;;
+	}
+	{ .mmi
+	  .mem.offset 0, 0
+	  st8.spill [r2] = in4, 16
+	  .mem.offset 8, 0
+	  st8.spill [r3] = in5, 16
+	  mov loc3 = r9		/* preserve language specific register */
+	  ;;
+	}
+	{ .mmi
+	  .mem.offset 0, 0
+	  st8 [r2] = in6, 16
+	  .mem.offset 8, 0
+	  st8 [r3] = in7, 24	/* adjust for f9 */
+	  mov loc4 = r10	/* preserve language specific register */
+	  ;;
+	}
+	{ .mii
+	  mov r18 = ar.unat	/* save it in La_ia64_regs */
+	  mov loc7 = out3	/* save it for _dl_call_pltexit */
+	  mov loc5 = r11	/* preserve language specific register */
+	}
+	{ .mmi
+	  stf.spill [r2] = f8, 32
+	  stf.spill [r3] = f9, 32
+	  mov out0 = r16	/* needed by _dl_fixup_profile */
+	  ;;
+	}
+	{ .mii
+	  mov ar.unat = r17	/* restore it for function call */
+	  mov loc8 = r16	/* save it for _dl_call_pltexit */
+	  nop.i 0x0
+	}
+	{ .mmi
+	  stf.spill [r2] = f10, 32
+	  stf.spill [r3] = f11, 32
+	  shl out1 = r15, 4
+	  ;;
+	}
+	{ .mmi
+	  stf.spill [r2] = f12, 32
+	  stf.spill [r3] = f13, 32
+	  /* Relocation record is 24 byte. */
+	  shladd out1 = r15, 3, out1
+	  ;;
+	}
+	{ .mmi
+	  stf.spill [r2] = f14, 32
+	  stf.spill [r3] = f15, 24
+	  mov loc9 = out1	/* save it for _dl_call_pltexit */
+	  ;;
+	}
+	{ .mmb
+	  st8 [r2] = r18	/* store ar.unat */
+	  st8 [r3] = loc10	/* store sp */
+	  br.call.sptk.many b0 = _dl_profile_fixup
+	}
+	{ .mii
+	  /* Skip the 16byte scratch area, 4 language specific GRs and
+	     8 incoming GRs to restore incoming fp registers.  */
+	  adds r2 = (4*8 + 8*8 + 16), r12
+	  adds r3 = (4*8 + 8*8 + 32), r12
+	  mov b6 = ret0
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f8 = [r2], 32
+	  ldf.fill f9 = [r3], 32
+	  mov gp = ret1
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f10 = [r2], 32
+	  ldf.fill f11 = [r3], 32
+	  mov r8 = loc2		/* restore struct value register */
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f12 = [r2], 32
+	  ldf.fill f13 = [r3], 32
+	  mov r9 = loc3		/* restore language specific register */
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f14 = [r2], 32
+	  ldf.fill f15 = [r3], 32
+	  mov r10 = loc4	/* restore language specific register */
+	  ;;
+	}
+	{ .mii
+	  ld8 r15 = [loc10]	/* load the new frame size */
+	  mov r11 = loc5	/* restore language specific register */
+	  ;;
+	  cmp.eq p6, p7 = -1, r15
+	  ;;
+	}
+	{ .mii
+(p7)	  cmp.eq p8, p9 = 0, r15
+(p6)	  mov b0 = loc1
+(p6)	  mov ar.lc = loc6
+	}
+	{ .mib
+	  nop.m 0x0
+(p6)	  mov ar.pfs = loc0
+(p6)	  br.cond.dptk.many .Lresolved
+	  ;;
+	}
+
+	/* At this point, the stack looks like
+
+	  +psp	free
+	  +16	La_ia64_regs
+	  sp	scratch
+
+	  We need to keep the current stack and call the resolved
+	  function by copying the r15 byte from sp + PLTENTER_FRAME_SIZE
+	  + 16 (scratch area) to sp + 16 (scratch area). Since stack
+	  has to be 16byte aligned, we around r15 up to 16byte.  */
+
+	{ .mbb
+(p9)	  adds r15 = 15, r15
+(p8)	  br.cond.dptk.many .Lno_new_frame
+	  nop.b 0x0
+	  ;;
+	}
+	{ .mmi
+	  and r15 = -16, r15
+	  ;;
+	  /* We don't copy the 16byte scatch area. Prepare r16/r17 as
+	     destination.  */
+	  sub r16 = r12, r15
+	  sub r17 = r12, r15
+	  ;;
+	}
+	{ .mii
+	  adds r16 = 16, r16
+	  adds r17 = 24, r17
+	  sub r12 = r12, r15		/* Adjust stack  */
+	  ;;
+	}
+	{ .mii
+	  nop.m 0x0
+	  shr r15 = r15, 4
+	  ;;
+	  adds r15 = -1, r15
+	  ;;
+	}
+	{ .mii
+	  /* Skip the 16byte scatch area. Prepare r2/r3 as source.  */
+	  adds r2 = 16, loc10
+	  adds r3 = 24, loc10
+	  mov ar.lc = r15
+	  ;;
+	}
+.Lcopy:
+	{ .mmi
+	  ld8 r18 = [r2], 16
+	  ld8 r19 = [r3], 16
+	  nop.i 0x0
+	  ;;
+	}
+	{ .mmb
+	  st8 [r16] = r18, 16
+	  st8 [r17] = r19, 16
+	  br.cloop.sptk.few .Lcopy
+	}
+.Lno_new_frame:
+	{ .mii
+	  mov out0 = in0
+	  mov out1 = in1
+	  mov out2 = in2
+	}
+	{ .mii
+	  mov out3 = in3
+	  mov out4 = in4
+	  mov out5 = in5
+	}
+	{ .mib
+	  mov out6 = in6
+	  mov out7 = in7
+	  /* Call the resolved function  */
+	  br.call.sptk.many b0 = b6
+	}
+	{ .mii
+	  /* Prepare stack for _dl_call_pltexit. Loc10 has the original
+	     stack pointer.  */
+	  adds r12 = -PLTEXIT_FRAME_SIZE, loc10
+	  adds r2 = -(PLTEXIT_FRAME_SIZE - 16), loc10
+	  adds r3 = -(PLTEXIT_FRAME_SIZE - 24), loc10
+	  ;;
+	}
+	{ .mmi
+	  /* Load all possible return values into buffer.  */
+	  st8 [r2] = r8, 16
+	  st8 [r3] = r9, 16
+	  mov out0 = loc8
+	  ;;
+	}
+	{ .mmi
+	  st8 [r2] = r10, 16
+	  st8 [r3] = r11, 24
+	  mov out1 = loc9
+	  ;;
+	}
+	{ .mmi
+	  stf.spill [r2] = f8, 32
+	  stf.spill [r3] = f9, 32
+	  mov out2 = loc7		/* Pointer to La_ia64_regs */
+	  ;;
+	}
+	{ .mmi
+	  stf.spill [r2] = f10, 32
+	  stf.spill [r3] = f11, 32
+	  adds out3 = 16, r12		/* Pointer to La_ia64_retval */
+	  ;;
+	}
+	{ .mmi
+	  stf.spill [r2] = f12, 32
+	  stf.spill [r3] = f13, 32
+	  /* We need to restore gp for _dl_call_pltexit. */
+	  mov gp = loc11
+	  ;;
+	}
+	{ .mmb
+	  stf.spill [r2] = f14
+	  stf.spill [r3] = f15
+	  br.call.sptk.many b0 = _dl_call_pltexit
+	}
+	{ .mmi
+	  /* Load all the non-floating and floating return values. Skip
+	     the 16byte scratch area.  */
+	  adds r2 = 16, r12
+	  adds r3 = 24, r12
+	  nop.i 0x0
+	  ;;
+	}
+	{ .mmi
+	  ld8 r8 = [r2], 16
+	  ld8 r9 = [r3], 16
+	  nop.i 0x0
+	  ;;
+	}
+	{ .mmi
+	  ld8 r10 = [r2], 16
+	  ld8 r11 = [r3], 24
+	  nop.i 0x0
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f8 = [r2], 32
+	  ldf.fill f9 = [r3], 32
+	  mov ar.lc = loc6
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f10 = [r2], 32
+	  ldf.fill f11 = [r3], 32
+	  mov ar.pfs = loc0
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f12 = [r2], 32
+	  ldf.fill f13 = [r3], 32
+	  mov b0 = loc1
+	  ;;
+	}
+	{ .mmi
+	  ldf.fill f14 = [r2]
+	  ldf.fill f15 = [r3]
+	  /* We know that the previous stack pointer, loc10, isn't 0.
+	     We use it to reload p7.  */
+	  cmp.ne p7, p0 = 0, loc10
+	  ;;
+	}
+.Lresolved:
+	{ .mmb
+	  .restore sp
+	  mov r12 = loc10
+(p7)	  br.ret.sptk.many b0
+	  ;;
+	}
+	/* An alloc is needed for the break system call to work. We
+	   don't care about the old value of the pfs register. After
+	   this alloc, we can't use any rotating registers. Otherwise
+	   assembler won't be happy. This has to be at the end.  */
+	{ .mmb
+	  .prologue
+	  .body
+	  alloc r2 = ar.pfs, 0, 0, 8, 0
+	  br.sptk.many b6
+	  ;;
+	}
+END(_dl_runtime_profile)
diff --git a/sysdeps/ia64/fpu/e_logl.c b/sysdeps/ia64/fpu/e_logl.c
deleted file mode 100644
index 41254ae60a..0000000000
--- a/sysdeps/ia64/fpu/e_logl.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Not needed. */
diff --git a/sysdeps/ia64/libc-tls.c b/sysdeps/ia64/libc-tls.c
index f1df4cd12e..3a6b8e5532 100644
--- a/sysdeps/ia64/libc-tls.c
+++ b/sysdeps/ia64/libc-tls.c
@@ -30,7 +30,7 @@ void *
 __tls_get_addr (size_t m, size_t offset)
 {
   dtv_t *dtv = THREAD_DTV ();
-  return (char *) dtv[1].pointer + offset;
+  return (char *) dtv[1].pointer.val + offset;
 }
 
 #endif
diff --git a/sysdeps/linkmap.h b/sysdeps/linkmap.h
new file mode 100644
index 0000000000..470b4d3e5f
--- /dev/null
+++ b/sysdeps/linkmap.h
@@ -0,0 +1,4 @@
+struct link_map_machine
+  {
+    /* empty by default */
+  };
diff --git a/sysdeps/m68k/bits/link.h b/sysdeps/m68k/bits/link.h
new file mode 100644
index 0000000000..9d0a94592f
--- /dev/null
+++ b/sysdeps/m68k/bits/link.h
@@ -0,0 +1,58 @@
+/* Copyright (C) 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on M68K.  */
+typedef struct La_m68k_regs
+{
+  uint32_t lr_a0;
+  uint32_t lr_a1;
+  uint32_t lr_sp;
+} La_m68k_regs;
+
+/* Return values for calls from PLT on M68K.  */
+typedef struct La_m68k_retval
+{
+  uint32_t lrv_d0;
+  uint32_t lrv_d1;
+  uint32_t lrv_a0;
+  long double lrv_fp0;
+} La_m68k_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_m68k_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+					uintptr_t *__refcook,
+					uintptr_t *__defcook,
+					La_m68k_regs *__regs,
+					unsigned int *__flags,
+					const char *__symname,
+					long int *__framesizep);
+extern unsigned int la_m68k_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+					 uintptr_t *__refcook,
+					 uintptr_t *__defcook,
+					 const La_m68k_regs *__inregs,
+					 La_m68k_retval *__outregs,
+					 const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index 146c5866a9..89d7106365 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  m68k version.
-   Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1996-2001, 2002, 2003, 2004, 2005 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
@@ -85,7 +85,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	{
 	  got[2] = (Elf32_Addr) &_dl_runtime_profile;
 
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    {
 	      /* This is the object we are looking for.  Say that we really
 		 want profiling and the timers are started.  */
@@ -101,36 +102,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
-"| Trampoline for " #fixup_name "\n\
-	.globl " #tramp_name "\n\
-	.type " #tramp_name ", @function\n\
-" #tramp_name ":\n\
-	| Save %a0 (struct return address) and %a1.\n\
-	move.l %a0, -(%sp)\n\
-	move.l %a1, -(%sp)\n\
-	| Call the real address resolver.\n\
-	jbsr " #fixup_name "\n\
-	| Restore register %a0 and %a1.\n\
-	move.l (%sp)+, %a1\n\
-	move.l (%sp)+, %a0\n\
-	| Pop parameters\n\
-	addq.l #8, %sp\n\
-	| Call real function.\n\
-	jmp (%d0)\n\
-	.size " #tramp_name ", . - " #tramp_name "\n"
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \
-     TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup));
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-asm (TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup) \
-     ".globl _dl_runtime_profile\n" \
-     ".set _dl_runtime_profile, _dl_runtime_resolve");
-#endif
 #define ELF_MACHINE_RUNTIME_FIXUP_ARGS long int save_a0, long int save_a1
 
 
@@ -216,9 +187,13 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
   return value;
 }
 
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER m68k_gnu_pltenter
+#define ARCH_LA_PLTEXIT m68k_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
@@ -236,9 +211,15 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
   else
     {
       const Elf32_Sym *const refsym = sym;
+#ifndef RTLD_BOOTSTRAP
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+#else
       Elf32_Addr value = RESOLVE (&sym, version, r_type);
+
       if (sym)
 	value += sym->st_value;
+#endif /* !RTLD_BOOTSTRAP */
 
       switch (r_type)
 	{
@@ -313,4 +294,4 @@ elf_machine_lazy_rel (struct link_map *map,
     _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/m68k/dl-trampoline.S b/sysdeps/m68k/dl-trampoline.S
new file mode 100644
index 0000000000..8791280371
--- /dev/null
+++ b/sysdeps/m68k/dl-trampoline.S
@@ -0,0 +1,129 @@
+/* PLT trampolines.  m68k version.
+   Copyright (C) 2005 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 <sysdep.h>
+
+	.text
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve, @function
+_dl_runtime_resolve:
+	| Save %a0 (struct return address) and %a1.
+	move.l %a0, -(%sp)
+	move.l %a1, -(%sp)
+	| Call the real address resolver.
+	jbsr _dl_fixup
+	| Restore register %a0 and %a1.
+	move.l (%sp)+, %a1
+	move.l (%sp)+, %a0
+	| Pop parameters
+	addq.l #8, %sp
+	| Call real function.
+	jmp (%d0)
+	.size _dl_runtime_resolve, . - _dl_runtime_resolve
+
+	.text
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile, @function
+_dl_runtime_profile:
+	pea 8(%sp)
+	move.l %a1, -(%sp)
+	move.l %a0, -(%sp)
+	pea -1.w
+	| Push parameters for _dl_profile_fixup
+	pea (%sp)
+	pea 8(%sp)
+	move.l 32(%sp), -(%sp)
+	move.l 32(%sp), -(%sp)
+	move.l 32(%sp), -(%sp)
+	subq.l #8, %sp
+	| Call the real address resolver.
+	jbsr _dl_profile_fixup
+	| Pop parameters
+	lea 28(%sp), %sp
+	move.l (%sp), %d1
+	jpl 1f
+	addq.l #4, %sp
+	| Restore register %a0 and %a1.
+	move.l (%sp)+, %a0
+	move.l (%sp)+, %a1
+	lea 12(%sp), %sp
+	| Call real function.
+	jmp (%d0)
+
+	/*
+	    +24     return address
+	    +20     PLT1
+	    +16     PLT2
+	    +12     %sp
+	    +8      %a1
+	    +4      %a0
+	   %sp      free
+	*/
+1:	move.l %a2, (%sp)
+	move.l %sp, %a2
+	move.l %sp, %a0
+	lea 28(%sp), %a1
+	| Round framesize up to even
+	addq.l #1, %d1
+	lsr #1, %d1
+	sub.l %d1, %a0
+	sub.l %d1, %a0
+	move.l %a0, %sp
+	jra 2f
+1:	move.w (%a1)+, (%a0)+
+2:	dbra %d1,1b
+	/*
+	   %a2+24  return address
+	   %a2+20  PLT1
+	   %a2+16  PLT2
+	   %a2+12  %sp
+	   %a2+8   %a1
+	   %a2+4   %a0
+	   %a2     %a2
+	   %sp     copied stack frame
+	*/
+
+	move.l 4(%a2), %a0
+	move.l 8(%a2), %a1
+	jsr (%d0)
+	move.l %a2, %sp
+	move.l (%sp)+, %a2
+	/*
+	    +20     return address
+	    +16     PLT1
+	    +12     PLT2
+	    +8      %sp
+	    +4      %a1
+	   %sp      %a0
+	*/
+	fmove.x %fp0, -(%sp)
+	move.l %d1, -(%sp)
+	move.l %d0, -(%sp)
+	pea (%sp)
+	pea 20(%sp)
+	move.l 40(%sp), -(%sp)
+	move.l 40(%sp), -(%sp)
+	jbsr _dl_call_pltexit
+	lea 16(%sp), %sp
+	move.l (%sp)+, %d0
+	move.l (%sp)+, %d1
+	fmove.x (%sp)+, %fp0
+	lea 20(%sp), %sp
+	rts
+	.size _dl_runtime_profile, . - _dl_runtime_profile
diff --git a/sysdeps/mach/hurd/tls.h b/sysdeps/mach/hurd/tls.h
index bc15b4dab6..cce42ef374 100644
--- a/sysdeps/mach/hurd/tls.h
+++ b/sysdeps/mach/hurd/tls.h
@@ -1,5 +1,5 @@
 /* Definitions for thread-local data handling.  Hurd version.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2005 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
@@ -23,6 +23,7 @@
 #if defined HAVE_TLS_SUPPORT && !defined ASSEMBLER
 
 # include <stddef.h>
+# include <stdbool.h>
 # include <mach/mig_errors.h>
 # include <mach.h>
 
@@ -31,7 +32,11 @@
 typedef union dtv
 {
   size_t counter;
-  void *pointer;
+  struct
+  {
+    void *val;
+    bool is_static;
+  } pointer;
 } dtv_t;
 
 
diff --git a/sysdeps/powerpc/powerpc32/bits/link.h b/sysdeps/powerpc/powerpc32/bits/link.h
new file mode 100644
index 0000000000..7f44087120
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/bits/link.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2004, 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on PPC32.  */
+typedef struct La_ppc32_regs
+{
+  uint32_t lr_reg[8];
+  double lr_fp[8];
+  uint32_t lr_vreg[12][4];
+  uint32_t lr_r1;
+  uint32_t lr_lr;
+} La_ppc32_regs;
+
+/* Return values for calls from PLT on PPC32.  */
+typedef struct La_ppc32_retval
+{
+  uint32_t lrv_r3;
+  uint32_t lrv_r4;
+  double lrv_fp[8];
+  uint32_t lrv_v2[4];
+} La_ppc32_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_ppc32_gnu_pltenter (Elf32_Sym *__sym,
+					 unsigned int __ndx,
+					 uintptr_t *__refcook,
+					 uintptr_t *__defcook,
+					 La_ppc32_regs *__regs,
+					 unsigned int *__flags,
+					 const char *__symname,
+					 long int *__framesizep);
+extern unsigned int la_ppc32_gnu_pltexit (Elf32_Sym *__sym,
+					  unsigned int __ndx,
+					  uintptr_t *__refcook,
+					  uintptr_t *__defcook,
+					  const La_ppc32_regs *__inregs,
+					  La_ppc32_retval *__outregs,
+					  const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.c b/sysdeps/powerpc/powerpc32/dl-machine.c
index 06960716b9..4120a02382 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.c
+++ b/sysdeps/powerpc/powerpc32/dl-machine.c
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation functions.  PowerPC version.
-   Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1995-2003, 2004, 2005 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
@@ -242,7 +242,8 @@ __elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 					 : _dl_runtime_resolve);
 	  Elf32_Word offset;
 
-	  if (profile && _dl_name_match_p (GLRO(dl_profile), map))
+	  if (profile && GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), map))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = map;
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index a8c1e3e490..de3b9e923a 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  PowerPC version.
-   Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 1995-2002, 2003, 2005 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
@@ -100,160 +100,6 @@ elf_machine_load_address (void)
 /* The PLT uses Elf32_Rela relocs.  */
 #define elf_machine_relplt elf_machine_rela
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  It is called
-   from code built in the PLT by elf_machine_runtime_setup.  */
-#if !defined PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
-	.section \".text\"	\n\
-	.align 2	\n\
-	.globl _dl_runtime_resolve	\n\
-	.type _dl_runtime_resolve,@function	\n\
-_dl_runtime_resolve:	\n\
- # We need to save the registers used to pass parameters, and register 0,\n\
- # which is used by _mcount; the registers are saved in a stack frame.\n\
-	stwu 1,-64(1)	\n\
-	stw 0,12(1)	\n\
-	stw 3,16(1)	\n\
-	stw 4,20(1)	\n\
- # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
-	mr 3,12	\n\
-	stw 5,24(1)	\n\
-	mr 4,11	\n\
-	stw 6,28(1)	\n\
-	mflr 0	\n\
- # We also need to save some of the condition register fields.\n\
-	stw 7,32(1)	\n\
-	stw 0,48(1)	\n\
-	stw 8,36(1)	\n\
-	mfcr 0	\n\
-	stw 9,40(1)	\n\
-	stw 10,44(1)	\n\
-	stw 0,8(1)	\n\
-	bl fixup@local	\n\
- # 'fixup' returns the address we want to branch to.\n\
-	mtctr 3	\n\
- # Put the registers back...\n\
-	lwz 0,48(1)	\n\
-	lwz 10,44(1)	\n\
-	lwz 9,40(1)	\n\
-	mtlr 0	\n\
-	lwz 8,36(1)	\n\
-	lwz 0,8(1)	\n\
-	lwz 7,32(1)	\n\
-	lwz 6,28(1)	\n\
-	mtcrf 0xFF,0	\n\
-	lwz 5,24(1)	\n\
-	lwz 4,20(1)	\n\
-	lwz 3,16(1)	\n\
-	lwz 0,12(1)	\n\
- # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
-	addi 1,1,64	\n\
-	bctr	\n\
-	.size	 _dl_runtime_resolve,.-_dl_runtime_resolve	\n\
-	\n\
-	.align 2	\n\
-	.globl _dl_prof_resolve	\n\
-	.type _dl_prof_resolve,@function	\n\
-_dl_prof_resolve:	\n\
- # We need to save the registers used to pass parameters, and register 0,\n\
- # which is used by _mcount; the registers are saved in a stack frame.\n\
-	stwu 1,-64(1)	\n\
-        stw 0,12(1)	\n\
-	stw 3,16(1)	\n\
-	stw 4,20(1)	\n\
- # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
-	mr 3,12	\n\
-	stw 5,24(1)	\n\
-	mr 4,11	\n\
-	stw 6,28(1)	\n\
-	mflr 5	\n\
- # We also need to save some of the condition register fields.\n\
-	stw 7,32(1)	\n\
-	stw 5,48(1)	\n\
-	stw 8,36(1)	\n\
-	mfcr 0	\n\
-	stw 9,40(1)	\n\
-	stw 10,44(1)	\n\
-	stw 0,8(1)	\n\
-	bl profile_fixup@local	\n\
- # 'fixup' returns the address we want to branch to.\n\
-	mtctr 3	\n\
- # Put the registers back...\n\
-	lwz 0,48(1)	\n\
-	lwz 10,44(1)	\n\
-	lwz 9,40(1)	\n\
-	mtlr 0	\n\
-	lwz 8,36(1)	\n\
-	lwz 0,8(1)	\n\
-	lwz 7,32(1)	\n\
-	lwz 6,28(1)	\n\
-	mtcrf 0xFF,0	\n\
-	lwz 5,24(1)	\n\
-	lwz 4,20(1)	\n\
-	lwz 3,16(1)	\n\
-        lwz 0,12(1)	\n\
- # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
-	addi 1,1,64	\n\
-	bctr	\n\
-	.size	 _dl_prof_resolve,.-_dl_prof_resolve	\n\
- # Undo '.section text'.\n\
-	.previous	\n\
-");
-#else
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
-	.section \".text\"	\n\
-	.align 2	\n\
-	.globl _dl_runtime_resolve	\n\
-	.globl _dl_prof_resolve	\n\
-	.type _dl_runtime_resolve,@function	\n\
-	.type _dl_prof_resolve,@function	\n\
-_dl_runtime_resolve:	\n\
-_dl_prof_resolve:	\n\
- # We need to save the registers used to pass parameters, and register 0,\n\
- # which is used by _mcount; the registers are saved in a stack frame.\n\
-	stwu 1,-64(1)	\n\
-	stw 0,12(1)	\n\
-	stw 3,16(1)	\n\
-	stw 4,20(1)	\n\
- # The code that calls this has put parameters for `fixup' in r12 and r11.\n\
-	mr 3,12	\n\
-	stw 5,24(1)	\n\
-	mr 4,11	\n\
-	stw 6,28(1)	\n\
-	mflr 0	\n\
- # We also need to save some of the condition register fields.\n\
-	stw 7,32(1)	\n\
-	stw 0,48(1)	\n\
-	stw 8,36(1)	\n\
-	mfcr 0	\n\
-	stw 9,40(1)	\n\
-	stw 10,44(1)	\n\
-	stw 0,8(1)	\n\
-	bl fixup@local	\n\
- # 'fixup' returns the address we want to branch to.\n\
-	mtctr 3	\n\
- # Put the registers back...\n\
-	lwz 0,48(1)	\n\
-	lwz 10,44(1)	\n\
-	lwz 9,40(1)	\n\
-	mtlr 0	\n\
-	lwz 8,36(1)	\n\
-	lwz 0,8(1)	\n\
-	lwz 7,32(1)	\n\
-	lwz 6,28(1)	\n\
-	mtcrf 0xFF,0	\n\
-	lwz 5,24(1)	\n\
-	lwz 4,20(1)	\n\
-	lwz 3,16(1)	\n\
-	lwz 0,12(1)	\n\
- # ...unwind the stack frame, and jump to the PLT entry we updated.\n\
-	addi 1,1,64	\n\
-	bctr	\n\
-	.size	 _dl_runtime_resolve,.-_dl_runtime_resolve	\n\
-");
-#endif
-
 /* Mask identifying addresses reserved for the user program,
    where the dynamic linker should not map anything.  */
 #define ELF_MACHINE_USER_ADDRESS_MASK	0xf0000000UL
@@ -328,9 +174,14 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
   return value + reloc->r_addend;
 }
 
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER ppc32_gnu_pltenter
+#define ARCH_LA_PLTEXIT ppc32_gnu_pltexit
+
 #endif /* dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Do the actual processing of a reloc, once its target address
    has been determined.  */
@@ -381,16 +232,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
     value = map->l_addr;
   else
     {
-# if defined USE_TLS && !defined RTLD_BOOTSTRAP
       sym_map = RESOLVE_MAP (&sym, version, r_type);
-      value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-# else
-      value = RESOLVE (&sym, version, r_type);
-#  ifndef RTLD_BOOTSTRAP
-      if (sym != NULL)
-#  endif
-	value += sym->st_value;
-# endif
+      value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
     }
   value += reloc->r_addend;
 #else
@@ -474,4 +317,4 @@ elf_machine_lazy_rel (struct link_map *map,
    DT_RELA table.  */
 #define ELF_MACHINE_PLTREL_OVERLAP 1
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/powerpc/powerpc32/dl-trampoline.S b/sysdeps/powerpc/powerpc32/dl-trampoline.S
new file mode 100644
index 0000000000..ea5ce7b45a
--- /dev/null
+++ b/sysdeps/powerpc/powerpc32/dl-trampoline.S
@@ -0,0 +1,174 @@
+/* PLT trampolines.  PPC32 version.
+   Copyright (C) 2005 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 <sysdep.h>
+
+	.section ".text"
+	.align 2
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve,@function
+_dl_runtime_resolve:
+ # We need to save the registers used to pass parameters, and register 0,
+ # which is used by _mcount; the registers are saved in a stack frame.
+	stwu r1,-64(r1)
+	stw r0,12(r1)
+	stw r3,16(r1)
+	stw r4,20(r1)
+ # The code that calls this has put parameters for `fixup' in r12 and r11.
+	mr r3,r12
+	stw r5,24(r1)
+	mr r4,r11
+	stw r6,28(r1)
+	mflr r0
+ # We also need to save some of the condition register fields
+	stw r7,32(r1)
+	stw r0,48(r1)
+	stw r8,36(r1)
+	mfcr r0
+	stw r9,40(r1)
+	stw r10,44(r1)
+	stw r0,8(r1)
+	bl _dl_fixup@local
+ # 'fixup' returns the address we want to branch to.
+	mtctr r3
+ # Put the registers back...
+	lwz r0,48(r1)
+	lwz r10,44(r1)
+	lwz r9,40(r1)
+	mtlr r0
+	lwz r8,36(r1)
+	lwz r0,8(r1)
+	lwz r7,32(r1)
+	lwz r6,28(r1)
+	mtcrf 0xFF,r0
+	lwz r5,24(r1)
+	lwz r4,20(r1)
+	lwz r3,16(r1)
+	lwz r0,12(r1)
+ # ...unwind the stack frame, and jump to the PLT entry we updated.
+	addi r1,r1,64
+	bctr
+	.size	 _dl_runtime_resolve,.-_dl_runtime_resolve
+
+	.align 2
+	.globl _dl_prof_resolve
+	.type _dl_prof_resolve,@function
+_dl_prof_resolve:
+ # We need to save the registers used to pass parameters, and register 0,
+ # which is used by _mcount; the registers are saved in a stack frame.
+	stwu r1,-320(r1)
+	/* Stack layout:
+
+	  +312   stackframe
+	  +308   lr
+	  +304   r1
+	  +288   v12
+	  +272   v11
+	  +256   v10
+	  +240   v9
+	  +224   v8
+	  +208   v7
+	  +192   v6
+	  +176   v5
+	  +160   v4
+	  +144   v3
+	  +128   v2
+	  +112   v1
+	  +104   fp8
+	  +96    fp7
+	  +88    fp6
+	  +80    fp5
+	  +72    fp4
+	  +64    fp3
+	  +56    fp2
+	  +48    fp1
+	  +44    r10
+	  +40    r9
+	  +36    r8
+	  +32    r7
+	  +28    r6
+	  +24    r5
+	  +20    r4
+	  +16    r3
+	  +12    r0
+	  +8     cr
+	   r1    link
+	*/
+        stw r0,12(r1)
+	stw r3,16(r1)
+	stw r4,20(r1)
+ # The code that calls this has put parameters for `fixup' in r12 and r11.
+	mr r3,r12
+	stw r5,24(r1)
+	mr r4,r11
+	stw r6,28(r1)
+	mflr r5
+ # We also need to save some of the condition register fields.
+	stw r7,32(r1)
+	stw r5,308(r1)
+	stw r8,36(r1)
+	mfcr r0
+	stw r9,40(r1)
+	stw r10,44(r1)
+	stw r0,8(r1)
+ # Save the floating point registers
+	stfd fp1,48(r1)
+	stfd fp2,56(r1)
+	stfd fp3,64(r1)
+	stfd fp4,72(r1)
+	stfd fp5,80(r1)
+	stfd fp6,88(r1)
+	stfd fp7,96(r1)
+	stfd fp8,104(r1)
+ # XXX TODO: store vmx registers
+ # Load the extra parameters.
+	addi r6,r1,16
+	addi r7,r1,312
+	li r0,-1
+	stw r0,0(r7)
+	bl _dl_profile_fixup@local
+ # 'fixup' returns the address we want to branch to.
+	mtctr r3
+ # Put the registers back...
+	lwz r0,308(r1)
+	lwz r10,44(r1)
+	lwz r9,40(r1)
+	mtlr r0
+	lwz r8,36(r1)
+	lwz r0,8(r1)
+	lwz r7,32(r1)
+	lwz r6,28(r1)
+	mtcrf 0xFF,r0
+	lwz r5,24(r1)
+	lwz r4,20(r1)
+	lwz r3,16(r1)
+        lwz r0,12(r1)
+ # Load the floating point registers.
+	lfd fp1,48(r1)
+	lfd fp2,56(r1)
+	lfd fp3,64(r1)
+	lfd fp4,72(r1)
+	lfd fp5,80(r1)
+	lfd fp6,88(r1)
+	lfd fp7,96(r1)
+	lfd fp8,104(r1)
+ # ...unwind the stack frame, and jump to the PLT entry we updated.
+	addi r1,r1,320
+	bctr
+	.size	 _dl_prof_resolve,.-_dl_prof_resolve
diff --git a/sysdeps/powerpc/powerpc64/bits/link.h b/sysdeps/powerpc/powerpc64/bits/link.h
new file mode 100644
index 0000000000..863336241a
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/bits/link.h
@@ -0,0 +1,109 @@
+/* Copyright (C) 2004, 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+#if __ELF_NATIVE_CLASS == 32
+
+/* Registers for entry into PLT on PPC32.  */
+typedef struct La_ppc32_regs
+{
+  uint32_t lr_reg[8];
+  double lr_fp[8];
+  uint32_t lr_vreg[12][4];
+  uint32_t lr_r1;
+  uint32_t lr_lr;
+} La_ppc32_regs;
+
+/* Return values for calls from PLT on PPC32.  */
+typedef struct La_ppc32_retval
+{
+  uint32_t lrv_r3;
+  uint32_t lrv_r4;
+  double lrv_fp[8];
+  uint32_t lrv_v2[4];
+} La_ppc32_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_ppc32_gnu_pltenter (Elf32_Sym *__sym,
+					 unsigned int __ndx,
+					 uintptr_t *__refcook,
+					 uintptr_t *__defcook,
+					 La_ppc32_regs *__regs,
+					 unsigned int *__flags,
+					 const char *__symname,
+					 long int *__framesizep);
+extern unsigned int la_ppc32_gnu_pltexit (Elf32_Sym *__sym,
+					  unsigned int __ndx,
+					  uintptr_t *__refcook,
+					  uintptr_t *__defcook,
+					  const La_ppc32_regs *__inregs,
+					  La_ppc32_retval *__outregs,
+					  const char *symname);
+
+__END_DECLS
+
+#else
+
+/* Registers for entry into PLT on PPC64.  */
+typedef struct La_ppc64_regs
+{
+  uint64_t lr_reg[8];
+  double lr_fp[13];
+  uint64_t __padding;
+  uint32_t lr_vreg[12][4];
+  uint64_t lr_r1;
+  uint64_t lr_lr;
+} La_ppc64_regs;
+
+/* Return values for calls from PLT on PPC64.  */
+typedef struct La_ppc64_retval
+{
+  uint64_t lrv_r3;
+  uint64_t lrv_r4;
+  double lrv_fp[8];
+  uint32_t lrv_v2[4];
+} La_ppc64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_ppc64_gnu_pltenter (Elf64_Sym *__sym,
+					 unsigned int __ndx,
+					 uintptr_t *__refcook,
+					 uintptr_t *__defcook,
+					 La_ppc64_regs *__regs,
+					 unsigned int *__flags,
+					 const char *__symname,
+					 long int *__framesizep);
+extern unsigned int la_ppc64_gnu_pltexit (Elf64_Sym *__sym,
+					  unsigned int __ndx,
+					  uintptr_t *__refcook,
+					  uintptr_t *__defcook,
+					  const La_ppc64_regs *__inregs,
+					  La_ppc64_retval *__outregs,
+					  const char *symname);
+
+__END_DECLS
+
+#endif
diff --git a/sysdeps/powerpc/powerpc64/dl-lookupcfg.h b/sysdeps/powerpc/powerpc64/dl-lookupcfg.h
index e502941015..e69de29bb2 100644
--- a/sysdeps/powerpc/powerpc64/dl-lookupcfg.h
+++ b/sysdeps/powerpc/powerpc64/dl-lookupcfg.h
@@ -1,22 +0,0 @@
-/* Configuration of lookup functions.  PowerPC64 version.
-   Copyright (C) 2002 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.  */
-
-/* Return the symbol map from the symbol lookup function.  */
-
-#define DL_LOOKUP_RETURNS_MAP 1
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 3fcf77df71..5ddc22e3c9 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -1,6 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.
    PowerPC64 version.
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -107,92 +107,6 @@ elf_machine_dynamic (void)
 /* The PLT uses Elf64_Rela relocs.  */
 #define elf_machine_relplt elf_machine_rela
 
-/* This code gets called via a .glink stub which loads PLT0.  It is
-   used in dl-runtime.c to call the `fixup' function and then redirect
-   to the address `fixup' returns.
-
-   Enter with r0 = plt reloc index,
-   r2 = ld.so tocbase,
-   r11 = ld.so link map.  */
-
-#define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name) \
-  asm (".section \".text\"\n"						\
-"	.align	2\n"							\
-"	.type	" BODY_PREFIX #tramp_name ",@function\n"		\
-"	.section \".opd\",\"aw\"\n"					\
-"	.align	3\n"							\
-"	.globl	" #tramp_name "\n"					\
-"	" ENTRY_2(tramp_name) "\n"					\
-#tramp_name ":\n"							\
-"	" OPD_ENT(tramp_name) "\n"					\
-"	.previous\n"							\
-BODY_PREFIX #tramp_name ":\n"						\
-/* We need to save the registers used to pass parameters, ie. r3 thru	\
-   r10; the registers are saved in a stack frame.  */			\
-"	stdu	1,-128(1)\n"						\
-"	std	3,48(1)\n"						\
-"	mr	3,11\n"							\
-"	std	4,56(1)\n"						\
-"	sldi	4,0,1\n"						\
-"	std	5,64(1)\n"						\
-"	add	4,4,0\n"						\
-"	std	6,72(1)\n"						\
-"	sldi	4,4,3\n"						\
-"	std	7,80(1)\n"						\
-"	mflr	0\n"							\
-"	std	8,88(1)\n"						\
-/* Store the LR in the LR Save area of the previous frame.  */    	\
-"	std	0,128+16(1)\n"						\
-"	mfcr	0\n"							\
-"	std	9,96(1)\n"						\
-"	std	10,104(1)\n"						\
-/* I'm almost certain we don't have to save cr...  be safe.  */    	\
-"	std	0,8(1)\n"						\
-"	bl	" DOT_PREFIX #fixup_name "\n"				\
-/* Put the registers back.  */						\
-"	ld	0,128+16(1)\n"						\
-"	ld	10,104(1)\n"						\
-"	ld	9,96(1)\n"						\
-"	ld	8,88(1)\n"						\
-"	ld	7,80(1)\n"						\
-"	mtlr	0\n"							\
-"	ld	0,8(1)\n"						\
-"	ld	6,72(1)\n"						\
-"	ld	5,64(1)\n"						\
-"	ld	4,56(1)\n"						\
-"	mtcrf	0xFF,0\n"						\
-/* Load the target address, toc and static chain reg from the function  \
-   descriptor returned by fixup.  */					\
-"	ld	0,0(3)\n"						\
-"	ld	2,8(3)\n"						\
-"	mtctr	0\n"							\
-"	ld	11,16(3)\n"						\
-"	ld	3,48(1)\n"						\
-/* Unwind the stack frame, and jump.  */				\
-"	addi	1,1,128\n"						\
-"	bctr\n"								\
-".LT_" #tramp_name ":\n"						\
-"	.long 0\n"							\
-"	.byte 0x00,0x0c,0x24,0x40,0x00,0x00,0x00,0x00\n"		\
-"	.long .LT_" #tramp_name "-" BODY_PREFIX #tramp_name "\n"	\
-"	.short .LT_" #tramp_name "_name_end-.LT_" #tramp_name "_name_start\n" \
-".LT_" #tramp_name "_name_start:\n"					\
-"	.ascii \"" #tramp_name "\"\n"					\
-".LT_" #tramp_name "_name_end:\n"					\
-"	.align 2\n"							\
-"	" END_2(tramp_name) "\n"					\
-"	.previous");
-
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
-  TRAMPOLINE_TEMPLATE (_dl_profile_resolve, profile_fixup);
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE			\
-  TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup);	\
-  void _dl_runtime_resolve (void);			\
-  strong_alias (_dl_runtime_resolve, _dl_profile_resolve);
-#endif
 
 #ifdef HAVE_INLINED_SYSCALLS
 /* We do not need _dl_starting_up.  */
@@ -420,7 +334,8 @@ elf_machine_runtime_setup (struct link_map *map, int lazy, int profile)
 
 	  resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve
 					   : _dl_runtime_resolve);
-	  if (profile && _dl_name_match_p (GLRO(dl_profile), map))
+	  if (profile && GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), map))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = map;
@@ -545,6 +460,11 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
   return value + reloc->r_addend;
 }
 
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER ppc64_gnu_pltenter
+#define ARCH_LA_PLTEXIT ppc64_gnu_pltexit
+
 #endif /* dl_machine_h */
 
 #ifdef RESOLVE_MAP
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S
new file mode 100644
index 0000000000..316f17a405
--- /dev/null
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S
@@ -0,0 +1,196 @@
+/* PLT trampolines.  PPC64 version.
+   Copyright (C) 2005 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 <sysdep.h>
+
+	.section ".text"
+
+EALIGN(_dl_runtime_resolve, 4, 0)
+/* We need to save the registers used to pass parameters, ie. r3 thru
+   r10; the registers are saved in a stack frame.  */
+	stdu	r1,-128(r1)
+	std	r3,48(r1)
+	mr	r3,r11
+	std	r4,56(r1)
+	sldi	r4,r0,1
+	std	r5,64(r1)
+	add	r4,r4,r0
+	std	r6,72(r1)
+	sldi	r4,r4,3
+	std	r7,80(r1)
+	mflr	r0
+	std	r8,88(r1)
+/* Store the LR in the LR Save area of the previous frame.  */
+	std	r0,128+16(r1)
+	mfcr	r0
+	std	r9,96(r1)
+	std	r10,104(r1)
+/* I'm almost certain we don't have to save cr...  be safe.  */
+	std	r0,8(r1)
+	bl	JUMPTARGET(_dl_fixup)
+/* Put the registers back.  */
+	ld	r0,128+16(r1)
+	ld	r10,104(r1)
+	ld	r9,96(r1)
+	ld	r8,88(r1)
+	ld	r7,80(r1)
+	mtlr	r0
+	ld	r0,8(r1)
+	ld	r6,72(r1)
+	ld	r5,64(r1)
+	ld	r4,56(r1)
+	mtcrf	0xFF,r0
+/* Load the target address, toc and static chain reg from the function
+   descriptor returned by fixup.  */
+	ld	r0,0(r3)
+	ld	r2,8(r3)
+	mtctr	r0
+	ld	r11,16(r3)
+	ld	r3,48(r1)
+/* Unwind the stack frame, and jump.  */
+	addi	r1,r1,128
+	bctr
+END(_dl_runtime_resolve)
+
+
+
+EALIGN(_dl_profile_resolve, 4, 0)
+/* We need to save the registers used to pass parameters, ie. r3 thru
+   r10; the registers are saved in a stack frame.  */
+	stdu	r1,-448(r1)
+	/* Stack layout:
+
+	  +432   stackframe
+	  +424   lr
+	  +416   r1
+	  +400   v12
+	  +384   v11
+	  +368   v10
+	  +362   v9
+	  +336   v8
+	  +320   v7
+	  +304   v6
+	  +288   v5
+	  +272   v4
+	  +256   v3
+	  +240   v2
+	  +224   v1
+	  +216   free
+	  +208   fp13
+	  +200   fp12
+	  +192   fp11
+	  +184   fp10
+	  +176   fp9
+	  +168   fp8
+	  +160   fp7
+	  +152   fp6
+	  +144   fp5
+	  +136   fp4
+	  +128   fp3
+	  +120   fp2
+	  +112   fp1
+	  +104   r10
+	  +96    r9
+	  +88    r8
+	  +80    r7
+	  +72    r6
+	  +64    r5
+	  +56    r4
+	  +48    r3
+	  +8     cr
+	   r1    link
+	*/
+	std	r3,48(r1)
+	mr	r3,r11
+	std	r4,56(r1)
+	sldi	r4,r0,1
+	std	r5,64(r1)
+	add	r4,r4,0
+	std	r6,72(r1)
+	sldi	r4,r4,3
+	std	r7,80(r1)
+	mflr	r5
+	std	r8,88(r1)
+/* Store the LR in the LR Save area of the previous frame.  */
+/* XXX Do we have to do this?  */
+	std	r5,448+16(r1)
+	std	r5,424(r1)
+	mfcr	r0
+	std	r9,96(r1)
+	std	r10,104(r1)
+/* I'm almost certain we don't have to save cr...  be safe.  */
+	std	r0,8(r1)
+/* Save floating registers.  */
+	stfd	fp1,112(r1)
+	stfd	fp2,120(r1)
+	stfd	fp3,128(r1)
+	stfd	fp4,136(r1)
+	stfd	fp5,144(r1)
+	stfd	fp6,152(r1)
+	stfd	fp7,160(r1)
+	stfd	fp8,168(r1)
+	stfd	fp9,176(r1)
+	stfd	fp10,184(r1)
+	stfd	fp11,192(r1)
+	stfd	fp12,200(r1)
+	stfd	fp13,208(r1)
+/* XXX TODO: store vmx registers.  */
+/* Load the extra parameters.  */
+	addi	r6,r1,48
+	addi	r7,r1,432
+	li	r0,-1
+	stdu	r0,0(r7)
+	bl	JUMPTARGET(_dl_profile_fixup)
+/* Put the registers back.  */
+	ld	r0,448+16(r1)
+	ld	r10,104(r1)
+	ld	r9,96(r1)
+	ld	r8,88(r1)
+	ld	r7,80(r1)
+	mtlr	r0
+	ld	r0,8(r1)
+	ld	r6,72(r1)
+	ld	r5,64(r1)
+	ld	r4,56(r1)
+	mtcrf	0xFF,r0
+/* Load the target address, toc and static chain reg from the function
+   descriptor returned by fixup.  */
+	ld	r0,0(r3)
+	ld	r2,8(r3)
+	mtctr	r0
+	ld	r11,16(r3)
+	ld	r3,48(r1)
+/* Load the floating point registers.  */
+	lfd	fp1,112(r1)
+	lfd	fp2,120(r1)
+	lfd	fp3,128(r1)
+	lfd	fp4,136(r1)
+	lfd	fp5,144(r1)
+	lfd	fp6,152(r1)
+	lfd	fp7,160(r1)
+	lfd	fp8,168(r1)
+	lfd	fp9,176(r1)
+	lfd	fp10,184(r1)
+	lfd	fp11,192(r1)
+	lfd	fp12,200(r1)
+	lfd	fp13,208(r1)
+/* Unwind the stack frame, and jump.  */
+	addi	r1,r1,448
+	bctr
+END(_dl_profile_resolve)
diff --git a/sysdeps/powerpc/tst-stack-align.h b/sysdeps/powerpc/tst-stack-align.h
new file mode 100644
index 0000000000..99a0ffcef7
--- /dev/null
+++ b/sysdeps/powerpc/tst-stack-align.h
@@ -0,0 +1,47 @@
+/* Copyright (C) 2005 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 <stdio.h>
+#include <stdint.h>
+
+#define TEST_STACK_ALIGN() \
+  ({									     \
+    /* Altivec __vector int etc. needs 16byte aligned stack.		     \
+       Instead of using altivec.h here, use aligned attribute instead.  */   \
+    struct _S								     \
+      {									     \
+        int _i __attribute__((aligned (16)));				     \
+	int _j[3];							     \
+      } _s = { ._i = 18, ._j[0] = 19, ._j[1] = 20, ._j[2] = 21 };	     \
+    double _d = 12.0;							     \
+    long double _ld = 15.0;						     \
+    int _ret = 0;							     \
+    printf ("__vector int:  { %d, %d, %d, %d } %p %zu\n", _s._i, _s._j[0],   \
+            _s._j[1], _s._j[2], &_s, __alignof (_s));			     \
+    if ((((uintptr_t) &_s) & (__alignof (_s) - 1)) != 0)		     \
+      _ret = 1;								     \
+									     \
+    printf ("double:  %g %p %zu\n", _d, &_d, __alignof (double));	     \
+    if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0)		     \
+      _ret = 1;								     \
+									     \
+    printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double));    \
+    if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0)	     \
+      _ret = 1;								     \
+    _ret;								     \
+    })
diff --git a/sysdeps/s390/bits/link.h b/sysdeps/s390/bits/link.h
index fc1fba363a..70f0043820 100644
--- a/sysdeps/s390/bits/link.h
+++ b/sysdeps/s390/bits/link.h
@@ -1,13 +1,111 @@
-#if __WORDSIZE == 64
-struct link_map_machine
-  {
-    Elf64_Addr plt; /* Address of .plt + 0x2e */
-    Elf64_Addr gotplt; /* Address of .got + 0x18 */
-  };
+/* Copyright (C) 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+#if __ELF_NATIVE_CLASS == 32
+
+/* Registers for entry into PLT on s390-32.  */
+typedef struct La_s390_32_regs
+{
+  uint32_t lr_r2;
+  uint32_t lr_r3;
+  uint32_t lr_r4;
+  uint32_t lr_r5;
+  uint32_t lr_r6;
+  double lr_fp0;
+  double lr_fp2;
+} La_s390_32_regs;
+
+/* Return values for calls from PLT on s390-32.  */
+typedef struct La_s390_32_retval
+{
+  uint32_t lrv_r2;
+  uint32_t lrv_r3;
+  double lrv_fp0;
+} La_s390_32_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_s390_32_gnu_pltenter (Elf32_Sym *__sym,
+					   unsigned int __ndx,
+					   uintptr_t *__refcook,
+					   uintptr_t *__defcook,
+					   La_s390_32_regs *__regs,
+					   unsigned int *__flags,
+					   const char *__symname,
+					   long int *__framesizep);
+extern unsigned int la_s390_32_gnu_pltexit (Elf32_Sym *__sym,
+					    unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					    const La_s390_32_regs *__inregs,
+					    La_s390_32_retval *__outregs,
+					    const char *symname);
+
+__END_DECLS
+
 #else
-struct link_map_machine
-  {
-    Elf32_Addr plt; /* Address of .plt + 0x2c */
-    Elf32_Addr gotplt; /* Address of .got + 0x0c */
-  };
+
+/* Registers for entry into PLT on s390-64.  */
+typedef struct La_s390_64_regs
+{
+  uint64_t lr_r2;
+  uint64_t lr_r3;
+  uint64_t lr_r4;
+  uint64_t lr_r5;
+  uint64_t lr_r6;
+  double lr_fp0;
+  double lr_fp2;
+  double lr_fp4;
+  double lr_fp6;
+} La_s390_64_regs;
+
+/* Return values for calls from PLT on s390-64.  */
+typedef struct La_s390_64_retval
+{
+  uint64_t lrv_r2;
+  double lrv_fp0;
+} La_s390_64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_s390_64_gnu_pltenter (Elf64_Sym *__sym,
+					   unsigned int __ndx,
+					   uintptr_t *__refcook,
+					   uintptr_t *__defcook,
+					   La_s390_64_regs *__regs,
+					   unsigned int *__flags,
+					   const char *__symname,
+					   long int *__framesizep);
+extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym,
+					    unsigned int __ndx,
+					    uintptr_t *__refcook,
+					    uintptr_t *__defcook,
+					    const La_s390_64_regs *__inregs,
+					    La_s390_64_retval *__outregs,
+					    const char *symname);
+
+__END_DECLS
+
 #endif
diff --git a/sysdeps/s390/bits/linkmap.h b/sysdeps/s390/bits/linkmap.h
new file mode 100644
index 0000000000..fc1fba363a
--- /dev/null
+++ b/sysdeps/s390/bits/linkmap.h
@@ -0,0 +1,13 @@
+#if __WORDSIZE == 64
+struct link_map_machine
+  {
+    Elf64_Addr plt; /* Address of .plt + 0x2e */
+    Elf64_Addr gotplt; /* Address of .got + 0x18 */
+  };
+#else
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt + 0x2c */
+    Elf32_Addr gotplt; /* Address of .got + 0x0c */
+  };
+#endif
diff --git a/sysdeps/s390/bits/string.h b/sysdeps/s390/bits/string.h
index 7134827eb0..d83df39bb2 100644
--- a/sysdeps/s390/bits/string.h
+++ b/sysdeps/s390/bits/string.h
@@ -51,7 +51,7 @@ strlen (__const char *__str)
 			  "0: srst  %0,%1\n"
 			  "   jo    0b\n"
 			  : "+&a" (__ptr), "+&a" (__tmp) : 
-			  : "cc", "0" );
+			  : "cc", "memory", "0" );
     return (size_t) (__ptr - __str);
 }
 #endif
@@ -105,7 +105,7 @@ strncpy (char *__dest, __const char *__src, size_t __n)
 #endif
                             "4:"
                             : "+&a" (__ptr), "+&a" (__n) : "a" (__diff)
-                            : "cc", "0" );
+                            : "cc", "memory", "0" );
     }
     return __ret;
 }
@@ -134,7 +134,7 @@ strcat(char *__dest, const char *__src)
 			  "0: mvst  %0,%1\n"
 			  "   jo    0b"
 			  : "+&a" (__ptr), "+&a" (__src) :
-			  : "cc", "0" );
+			  : "cc", "memory", "0" );
     return __ret;
 }
 #endif
@@ -157,7 +157,7 @@ strncat (char *__dest, __const char *__src, size_t __n)
 			    "0: srst  %0,%1\n"
 			  "   jo    0b\n"
 			    : "+&a" (__ptr), "+&a" (__tmp) :
-			    : "cc", "0" );
+			    : "cc", "memory", "0" );
 
       __diff = (size_t) (__ptr - __src);
       __tmp = (char *) __src;
@@ -175,7 +175,7 @@ strncat (char *__dest, __const char *__src, size_t __n)
                             "   stc   0,1(%2,%0)\n"
 			    "2:"
                             : "+&a" (__tmp), "+&a" (__n) : "a" (__diff)
-                            : "cc", "0" );
+                            : "cc", "memory", "0" );
 
     }
     return __ret;
@@ -200,7 +200,7 @@ memchr (__const void *__str, int __c, size_t __n)
                           "   la    %0,0\n"
                           "1:"
 			  : "+&a" (__ptr), "+&a" (__tmp) : "d" (__c)
-			  : "cc", "0" );
+			  : "cc", "memory", "0" );
     return __ptr;
 }
 #endif
@@ -222,7 +222,7 @@ strcmp (__const char *__s1, __const char *__s2)
 			  "   ipm   %0\n"
 			  "   srl   %0,28"
 			  : "=d" (__ret), "+&a" (__p1), "+&a" (__p2) : 
-			  : "cc", "0" );
+			  : "cc", "memory", "0" );
     __ret = (__ret == 0) ? 0 : (__ret == 1) ? -1 : 1;
     return __ret;
 }
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
index 52922a813b..8bbf858fbf 100644
--- a/sysdeps/s390/s390-32/dl-machine.h
+++ b/sysdeps/s390/s390-32/dl-machine.h
@@ -1,5 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  S390 Version.
-   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
    Contributed by Carl Pederson & Martin Schwidefsky.
    This file is part of the GNU C Library.
 
@@ -21,7 +22,6 @@
 #ifndef dl_machine_h
 #define dl_machine_h
 
-
 #define ELF_MACHINE_NAME "s390"
 
 #include <sys/param.h>
@@ -112,7 +112,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	{
 	  got[2] = (Elf32_Addr) &_dl_runtime_profile;
 
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = l;
@@ -126,124 +127,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-
-/* s390:
-   Arguments are in register.
-   r2 - r7 holds the original parameters for the function call, fixup
-   and trampoline code use r0-r5 and r14-15. For the correct function
-   call r2-r5 and r14-15 must be restored.
-   Arguments from the PLT are stored at 24(r15) and 28(r15)
-   and must be moved to r2 and r3 for the fixup call (see elf32-s390.c
-   in the binutils for the PLT code).
-   Fixup function address in r2.
-*/
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-  asm ( "\
-    .text\n\
-    .globl _dl_runtime_resolve\n\
-    .type _dl_runtime_resolve, @function\n\
-    .align 16\n\
-    " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-    # save registers\n\
-    stm    2,5,32(15)\n\
-    st     14,48(15)\n\
-    lr     0,15\n\
-    ahi    15,-96\n\
-    " CFI_ADJUST_CFA_OFFSET(96)"\n\
-    st     0,0(15)\n\
-    # load args saved by PLT\n\
-    lm     2,3,120(15)\n\
-    basr   1,0\n\
-0:  ahi    1,1f-0b\n\
-    l      14,0(1)\n\
-    bas    14,0(14,1)   # call fixup\n\
-    lr     1,2          # function addr returned in r2\n\
-    # restore registers\n\
-    ahi    15,96\n\
-    " CFI_ADJUST_CFA_OFFSET(-96)" \n\
-    l      14,48(15)\n\
-    lm     2,5,32(15)\n\
-    br     1\n\
-1:  .long  fixup-1b\n\
-    " CFI_ENDPROC "\n\
-    .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
-    .globl _dl_runtime_profile\n\
-    .type _dl_runtime_profile, @function\n\
-    .align 16\n\
-    " CFI_STARTPROC "\n\
-_dl_runtime_profile:\n\
-    # save registers\n\
-    stm    2,5,32(15)\n\
-    st     14,48(15)\n\
-    lr     0,15\n\
-    ahi    15,-96\n\
-    " CFI_ADJUST_CFA_OFFSET(96)"\n\
-    st     0,0(15)\n\
-    # load args saved by PLT\n\
-    lm     2,3,120(15)\n\
-    # load return address as third parameter\n\
-    lr     4,14\n\
-    basr   1,0\n\
-0:  ahi    1,1f-0b\n\
-    l      14,0(1)\n\
-    bas    14,0(14,1)   # call fixup\n\
-    lr     1,2          # function addr returned in r2\n\
-    # restore registers\n\
-    ahi    15,96\n\
-    " CFI_ADJUST_CFA_OFFSET(-96)" \n\
-    l      14,48(15)\n\
-    lm     2,5,32(15)\n\
-    br     1\n\
-1:  .long  profile_fixup-1b\n\
-    " CFI_ENDPROC "\n\
-    .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-  asm ( "\
-    .text\n\
-    .globl _dl_runtime_resolve\n\
-    .globl _dl_runtime_profile\n\
-    .type _dl_runtime_resolve, @function\n\
-    .type _dl_runtime_profile, @function\n\
-    .align 16\n\
-    " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
-    # save registers\n\
-    stm    2,5,32(15)\n\
-    st     14,48(15)\n\
-    lr     0,15\n\
-    ahi    15,-96\n\
-    " CFI_ADJUST_CFA_OFFSET(96)"\n\
-    st     0,0(15)\n\
-    # load args saved by PLT\n\
-    lm     2,3,120(15)\n\
-    # load return address as third parameter\n\
-    lr     4,14\n\
-    basr   1,0\n\
-0:  ahi    1,1f-0b\n\
-    l      14,0(1)\n\
-    bas    14,0(14,1)   # call fixup\n\
-    lr     1,2          # function addr returned in r2\n\
-    # restore registers\n\
-    ahi    15,96\n\
-    " CFI_ADJUST_CFA_OFFSET(-96)" \n\
-    l      14,48(15)\n\
-    lm     2,5,32(15)\n\
-    br     1\n\
-1:  .long  fixup-1b\n\
-    " CFI_ENDPROC "\n\
-    .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-    .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#endif
-
 /* Mask identifying addresses reserved for the user program,
    where the dynamic linker should not map anything.  */
 #define ELF_MACHINE_USER_ADDRESS_MASK   0xf8000000UL
@@ -375,15 +258,20 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
   return value;
 }
 
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER s390_32_gnu_pltenter
+#define ARCH_LA_PLTEXIT s390_32_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 		  const Elf32_Sym *sym, const struct r_found_version *version,
 		  void *const reloc_addr_arg)
@@ -417,17 +305,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 #ifndef RESOLVE_CONFLICT_FIND_MAP
       const Elf32_Sym *const refsym = sym;
 #endif
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
-      Elf32_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
-      if (sym)
-# endif
-	value += sym->st_value;
-#endif /* use TLS and !RTLD_BOOTSTRAP */
 
       switch (r_type)
 	{
@@ -539,7 +418,8 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
     }
 }
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
 			   void *const reloc_addr_arg)
 {
@@ -547,7 +427,8 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
   *reloc_addr = l_addr + reloc->r_addend;
 }
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_lazy_rel (struct link_map *map,
 		      Elf32_Addr l_addr, const Elf32_Rela *reloc)
 {
@@ -567,4 +448,4 @@ elf_machine_lazy_rel (struct link_map *map,
     _dl_reloc_bad_type (map, r_type, 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/s390/s390-32/dl-trampoline.S b/sysdeps/s390/s390-32/dl-trampoline.S
new file mode 100644
index 0000000000..4ee2295b89
--- /dev/null
+++ b/sysdeps/s390/s390-32/dl-trampoline.S
@@ -0,0 +1,133 @@
+/* PLT trampolines.  s390 version.
+   Copyright (C) 2005 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.  */
+
+/* This code is used in dl-runtime.c to call the `fixup' function
+   and then redirect to the address it returns.  */
+
+/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
+ * with the following linkage:
+ *   r2 - r6 : parameter registers
+ *   f0, f2 : floating point parameter registers
+ *   24(r15), 28(r15) : PLT arguments PLT1, PLT2
+ *   96(r15) : additional stack parameters
+ * The normal clobber rules for function calls apply:
+ *   r0 - r5 : call clobbered
+ *   r6 - r13 :	 call saved
+ *   r14 : return address (call clobbered)
+ *   r15 : stack pointer (call saved)
+ *   f4, f6 : call saved
+ *   f0 - f3, f5, f7 - f15 : call clobbered
+ */
+
+#include <sysdep.h>
+
+	.text
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_resolve:
+	stm    %r2,%r5,32(%r15)		# save registers
+	st     %r14,8(%r15)
+	lr     %r0,%r15			# create stack frame
+	ahi    %r15,-96
+	cfi_adjust_cfa_offset (96)
+	st     0,0(%r15)
+	lm     %r2,%r3,120(%r15)	# load args saved by PLT
+	basr   %r1,0
+0:	l      %r14,1f-0b(%r1)
+	bas    %r14,0(%r14,%r1)		# call resolver
+	lr     %r1,%r2			# function addr returned in r2
+	ahi    %r15,96			# remove stack frame
+	cfi_adjust_cfa_offset (-96)
+	l      %r14,8(15)		# restore registers
+	lm     %r2,%r5,32(%r15)
+	br     %r1
+1:	.long  _dl_fixup - 0b
+	cfi_endproc
+	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_profile:
+	stm    %r2,%r6,32(%r15)		# save registers
+	std    %f0,56(%r15)
+	std    %f2,64(%r15)
+	st     %r6,8(%r15)
+	st     %r12,12(%r15)
+	st     %r14,16(%r15)
+	lr     %r12,%r15		# create stack frame
+	cfi_def_cfa_register (12)
+	ahi    %r15,-96
+	st     %r12,0(%r15)
+	lm     %r2,%r3,24(%r12)		# load arguments saved by PLT
+	lr     %r4,%r14			# return address as third parameter
+	basr   %r1,0
+0:	l      %r14,6f-0b(%r1)
+	la     %r5,32(%r12)		# pointer to struct La_s390_32_regs
+	la     %r6,20(%r12)		# long int * framesize
+	bas    %r14,0(%r14,%r1)		# call resolver
+	lr     %r1,%r2			# function addr returned in r2
+	icm    %r0,15,20(%r12)		# load & test framesize
+	jnm    2f
+	lm     %r2,%r6,32(%r12)
+	ld     %f0,56(%r12)
+	ld     %f2,64(%r12)
+	basr   %r14,%r1			# call resolved function
+1:	lr     %r15,%r12		# remove stack frame
+	cfi_def_cfa_register (15)
+	l      %r14,16(%r15)		# restore registers
+	l      %r12,12(%r15)
+	l      %r6,8(%r15)
+	br     %r14
+	cfi_def_cfa_register (12)
+2:	jz     4f			# framesize == 0 ?
+	ahi    %r0,7			# align framesize to 8
+	lhi    %r2,-8
+	nr     %r0,%r2
+	slr    %r15,%r0			# make room for framesize bytes
+	st     %r12,0(%r15)
+	la     %r2,96(%r15)
+	la     %r3,96(%r12)
+	srl    %r0,3
+3:	mvc    0(8,%r2),0(%r3)		# copy additional parameters
+	la     %r2,8(%r2)
+	la     %r3,8(%r3)
+	brct   %r0,3b
+4:	lm     %r2,%r6,32(%r12)		# load register parameters
+	ld     %f0,56(%r12)
+	ld     %f2,64(%r12)
+	basr   %r14,%r1			# call resolved function
+	stm    %r2,%r3,72(%r12)
+	std    %f0,80(%r12)
+	lm     %r2,%r3,24(%r12)		# load arguments saved by PLT
+	basr   %r1,0
+5:	l      %r14,7f-5b(%r1)
+	la     %r4,32(%r12)		# pointer to struct La_s390_32_regs
+	la     %r5,72(%r12)		# pointer to struct La_s390_32_retval
+	basr   %r14,%r1			# call _dl_call_pltexit	
+	j      1b
+6:	.long  _dl_profile_fixup - 0b
+7:	.long  _dl_call_pltexit - 5b
+	cfi_endproc
+	.size _dl_runtime_profile, .-_dl_runtime_profile
+
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
index 82ece0be0f..5026a2edad 100644
--- a/sysdeps/s390/s390-64/dl-machine.h
+++ b/sysdeps/s390/s390-64/dl-machine.h
@@ -1,6 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.
    64 bit S/390 Version.
-   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
 
@@ -105,7 +105,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	{
 	  got[2] = (Elf64_Addr) &_dl_runtime_profile;
 
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = l;
@@ -119,112 +120,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.	 */
-
-/* s390:
-   Arguments are in register.
-   r2 - r7 holds the original parameters for the function call, fixup
-   and trampoline code use r0-r5 and r14-15. For the correct function
-   call r2-r5 and r14-15 must be restored.
-   Arguments from the PLT are stored at 48(r15) and 56(r15)
-   and must be moved to r2 and r3 for the fixup call (see elf32-s390.c
-   in the binutils for the PLT code).
-   Fixup function address in r2.
-*/
-#ifndef PROF
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-  asm ( "\
-    .text\n\
-    .globl _dl_runtime_resolve\n\
-    .type _dl_runtime_resolve, @function\n\
-    .align 16\n\
-    " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-    # save registers\n\
-    stmg   2,5,64(15)\n\
-    stg	   14,96(15)\n\
-    lgr	   0,15\n\
-    aghi   15,-160\n\
-    " CFI_ADJUST_CFA_OFFSET(160)"\n\
-    stg	   0,0(15)\n\
-    # load args saved by PLT\n\
-    lmg	   2,3,208(15)\n\
-    brasl  14,fixup	# call fixup\n\
-    lgr	   1,2		# function addr returned in r2\n\
-    # restore registers\n\
-    aghi   15,160\n\
-    " CFI_ADJUST_CFA_OFFSET(-160)" \n\
-    lg	   14,96(15)\n\
-    lmg	   2,5,64(15)\n\
-    br	   1\n\
-    " CFI_ENDPROC "\n\
-    .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
-    .globl _dl_runtime_profile\n\
-    .type _dl_runtime_profile, @function\n\
-    .align 16\n\
-    " CFI_STARTPROC "\n\
-_dl_runtime_profile:\n\
-    # save registers\n\
-    stmg   2,5,64(15)\n\
-    stg	   14,96(15)\n\
-    lgr	   0,15\n\
-    aghi   15,-160\n\
-    " CFI_ADJUST_CFA_OFFSET(160)"\n\
-    stg	   0,0(15)\n\
-    # load args saved by PLT\n\
-    lmg	   2,3,208(15)\n\
-    # load return address as third parameter\n\
-    lgr	   4,14\n\
-    brasl  14,profile_fixup  # call fixup\n\
-    lgr	   1,2		# function addr returned in r2\n\
-    # restore registers\n\
-    aghi   15,160\n\
-    " CFI_ADJUST_CFA_OFFSET(-160)" \n\
-    lg	   14,96(15)\n\
-    lmg	   2,5,64(15)\n\
-    br	   1\n\
-    " CFI_ENDPROC "\n\
-    .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#else
-#define ELF_MACHINE_RUNTIME_TRAMPOLINE \
-  asm ( "\
-    .text\n\
-    .globl _dl_runtime_resolve\n\
-    .globl _dl_runtime_profile\n\
-    .type _dl_runtime_resolve, @function\n\
-    .type _dl_runtime_profile, @function\n\
-    .align 16\n\
-    " CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
-    # save registers\n\
-    stmg   2,5,64(15)\n\
-    stg	   14,96(15)\n\
-    lgr	   0,15\n\
-    aghi   15,-160\n\
-    " CFI_ADJUST_CFA_OFFSET(160)"\n\
-    stg	   0,0(15)\n\
-    # load args saved by PLT\n\
-    lmg	   2,3,208(15)\n\
-    # load return address as third parameter\n\
-    lgr	   4,14\n\
-    brasl  14,profile_fixup	 # call fixup\n\
-    lgr	   1,2		# function addr returned in r2\n\
-    # restore registers\n\
-    aghi   15,160\n\
-    " CFI_ADJUST_CFA_OFFSET(-160)" \n\
-    lg	   14,96(15)\n\
-    lmg	   2,5,64(15)\n\
-    br	   1\n\
-    " CFI_ENDPROC "\n\
-    .size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-    .size _dl_runtime_profile, .-_dl_runtime_profile\n\
-");
-#endif
-
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
    its return value is the user program's entry point.	*/
@@ -343,14 +238,19 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
   return value;
 }
 
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER s390_64_gnu_pltenter
+#define ARCH_LA_PLTEXIT s390_64_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 		  const Elf64_Sym *sym, const struct r_found_version *version,
 		  void *const reloc_addr_arg)
@@ -384,17 +284,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 #ifndef RESOLVE_CONFLICT_FIND_MAP
       const Elf64_Sym *const refsym = sym;
 #endif
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       Elf64_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
-      Elf64_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
-      if (sym)
-# endif
-	value += sym->st_value;
-#endif /* use TLS and !RTLD_BOOTSTRAP */
 
       switch (r_type)
 	{
@@ -518,7 +409,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
     }
 }
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
 			   void *const reloc_addr_arg)
 {
@@ -526,7 +418,8 @@ elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc,
   *reloc_addr = l_addr + reloc->r_addend;
 }
 
-static inline void
+auto inline void
+__attribute__ ((always_inline))
 elf_machine_lazy_rel (struct link_map *map,
 		      Elf64_Addr l_addr, const Elf64_Rela *reloc)
 {
@@ -546,4 +439,4 @@ elf_machine_lazy_rel (struct link_map *map,
     _dl_reloc_bad_type (map, r_type, 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/s390/s390-64/dl-trampoline.S b/sysdeps/s390/s390-64/dl-trampoline.S
new file mode 100644
index 0000000000..215d869803
--- /dev/null
+++ b/sysdeps/s390/s390-64/dl-trampoline.S
@@ -0,0 +1,126 @@
+/* PLT trampolines.  s390 version.
+   Copyright (C) 2005 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.  */
+
+/* The PLT stubs will call _dl_runtime_resolve/_dl_runtime_profile
+ * with the following linkage:
+ *   r2 - r6 : parameter registers
+ *   f0, f2, f4, f6 : floating point parameter registers
+ *   24(r15), 28(r15) : PLT arguments PLT1, PLT2
+ *   96(r15) : additional stack parameters
+ * The normal clobber rules for function calls apply:
+ *   r0 - r5 : call clobbered
+ *   r6 - r13 :	 call saved
+ *   r14 : return address (call clobbered)
+ *   r15 : stack pointer (call saved)
+ *   f1, f3, f5, f7 : call saved
+ *   f0 - f3, f5, f7 - f15 : call clobbered
+ */
+
+#include <sysdep.h>
+
+	.text
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_resolve:
+	stmg   2,5,64(15)	# save registers
+	stg    14,96(15)
+	lgr    0,15		# create stack frame
+	aghi   15,-160
+	cfi_adjust_cfa_offset (160)
+	stg    0,0(15)
+	lmg    2,3,208(15)	# load args saved by PLT
+	brasl  14,_dl_fixup	# call fixup
+	lgr    1,2		# function addr returned in r2
+	aghi   15,160		# remove stack frame
+	cfi_adjust_cfa_offset (-160)
+	lg     14,96(15)	# restore registers
+	lmg    2,5,64(15)
+	br     1
+	cfi_endproc
+	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile, @function
+	cfi_startproc
+	.align 16
+_dl_runtime_profile:
+	stmg   %r2,%r6,64(%r15)		# save registers
+	std    %f0,104(%r15)
+	std    %f2,112(%r15)
+	std    %f4,120(%r15)
+	std    %f6,128(%r15)
+	stg    %r6,16(%r15)
+	stg    %r12,24(%r15)
+	stg    %r14,32(%r15)
+	lgr    %r12,%r15		# create stack frame
+	cfi_def_cfa_register (12)
+	aghi   %r15,-160
+	stg    %r12,0(%r15)
+	lmg    %r2,%r3,48(%r12)		# load arguments saved by PLT
+	lgr    %r4,%r14			# return address as third parameter
+	la     %r5,64(%r12)		# pointer to struct La_s390_32_regs
+	la     %r6,40(%r12)		# long int * framesize
+	brasl  %r14,_dl_profile_fixup	# call resolver
+	lgr    %r1,%r2			# function addr returned in r2
+	lg     %r0,40(%r12)		# load framesize
+	ltgr   %r0,%r0
+	jnm    1f
+	lmg    %r2,%r6,64(%r12)
+	ld     %f0,104(%r12)
+	ld     %f2,112(%r12)
+	ld     %f4,120(%r12)
+	ld     %f6,128(%r12)
+	basr   %r14,%r1			# call resolved function
+0:	lr     %r15,%r12		# remove stack frame
+	cfi_def_cfa_register (15)
+	lg     %r14,32(%r15)		# restore registers
+	lg     %r12,24(%r15)
+	lg     %r6,16(%r15)
+	br     %r14
+	cfi_def_cfa_register (12)
+1:	jz     4f			# framesize == 0 ?
+	aghi   %r0,7			# align framesize to 8
+	nill   %r0,0xfff8
+	slgr   %r15,%r0			# make room for framesize bytes
+	stg    %r12,0(%r15)
+	la     %r2,160(%r15)
+	la     %r3,160(%r12)
+	srlg   %r0,%r0,3
+3:	mvc    0(8,%r2),0(%r3)		# copy additional parameters
+	la     %r2,8(%r2)
+	la     %r3,8(%r3)
+	brctg  %r0,3b
+4:	lmg    %r2,%r6,64(%r12)		# load register parameters
+	ld     %f0,104(%r12)
+	ld     %f2,112(%r12)
+	ld     %f4,120(%r12)
+	ld     %f6,128(%r12)
+	basr   %r14,%r1			# call resolved function
+	stg    %r2,136(%r12)
+	std    %f0,144(%r12)
+	lmg    %r2,%r3,48(%r12)		# load arguments saved by PLT
+	la     %r4,32(%r12)		# pointer to struct La_s390_32_regs
+	la     %r5,72(%r12)		# pointer to struct La_s390_32_retval
+	brasl  %r14,_dl_call_pltexit
+	j      0b
+	cfi_endproc
+	.size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/sh/bits/link.h b/sysdeps/sh/bits/link.h
index bb2fbb5f16..2826677336 100644
--- a/sysdeps/sh/bits/link.h
+++ b/sysdeps/sh/bits/link.h
@@ -1,5 +1,70 @@
-struct link_map_machine
-  {
-    Elf32_Addr plt; /* Address of .plt + 36 */
-    Elf32_Addr gotplt; /* Address of .got + 0x0c */
-  };
+/* Copyright (C) 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+/* Registers for entry into PLT on SH.  */
+typedef struct La_sh_regs
+{
+  uint32_t lr_r2;
+  uint32_t lr_r3;
+  uint32_t lr_r4;
+  uint32_t lr_r5;
+  uint32_t lr_r6;
+  uint32_t lr_r7;
+  uint32_t lr_fpscr;
+  float lr_fr4;
+  float lr_fr5;
+  float lr_fr6;
+  float lr_fr7;
+  float lr_fr8;
+  float lr_fr9;
+  float lr_fr10;
+  float lr_fr11;
+} La_sh_regs;
+
+/* Return values for calls from PLT on SH.  */
+typedef struct La_sh_retval
+{
+  uint32_t lrv_r0;
+  uint32_t lrv_r1;
+  float lrv_fr0;
+  float lrv_fr1;
+} La_sh_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_sh_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+				      uintptr_t *__refcook,
+				      uintptr_t *__defcook,
+				      La_sh_regs *__regs,
+				      unsigned int *__flags,
+				      const char *__symname,
+				      long int *__framesizep);
+extern unsigned int la_sh_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+				       uintptr_t *__refcook,
+				       uintptr_t *__defcook,
+				       const La_sh_regs *__inregs,
+				       La_sh_retval *__outregs,
+				       const char *symname);
+
+__END_DECLS
diff --git a/sysdeps/sh/bits/linkmap.h b/sysdeps/sh/bits/linkmap.h
new file mode 100644
index 0000000000..bb2fbb5f16
--- /dev/null
+++ b/sysdeps/sh/bits/linkmap.h
@@ -0,0 +1,5 @@
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt + 36 */
+    Elf32_Addr gotplt; /* Address of .got + 0x0c */
+  };
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index 271666a2a3..b66b4f0e42 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  SH version.
-   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+   Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -21,8 +21,6 @@
 #ifndef dl_machine_h
 #define dl_machine_h
 
-/* Only dummy. This doesn't work. */
-
 #define ELF_MACHINE_NAME "SH"
 
 #include <sys/param.h>
@@ -106,7 +104,9 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	{
 	  got[2] = (Elf32_Addr) &_dl_runtime_profile;
 	  /* Say that we really want profiling and the timers are started.  */
-	  GL(dl_profile_map) = l;
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
+	    GL(dl_profile_map) = l;
 	}
       else
 	/* This function will get called to fix up the GOT entry indicated by
@@ -116,273 +116,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.	 */
-
 #define ELF_MACHINE_RUNTIME_FIXUP_ARGS int plt_type
 
-#ifdef SHARED
-#define FUN_ADDR	"\
-	mov.l 1f,r2\n\
-	mova 1f,r0\n\
-        bra 2f\n\
-	 add r0,r2		! Get GOT address in r2\n\
-0:	.align 2\n\
-1:	.long _GLOBAL_OFFSET_TABLE_\n\
-2:	mov.l 3f,r0\n\
-	add r2,r0"
-#define GOTJMP(x)	#x "@GOTOFF"
-#else
-#define FUN_ADDR	"\
-	mov.l 3f,r0"
-#define GOTJMP(x)	#x
-#endif
-
-#ifdef HAVE_FPU
-#define FGR_SAVE	"\
-	sts.l	fpscr, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov	#8,r3\n\
-	swap.w	r3, r3\n\
-	lds	r3, fpscr\n\
-	fmov.s	fr11, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	fmov.s	fr10, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	fmov.s	fr9, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	fmov.s	fr8, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	fmov.s	fr7, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	fmov.s	fr6, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	fmov.s	fr5, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	fmov.s	fr4, @-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4)
-#define FGR_LOAD	"\
-	fmov.s	@r15+, fr4\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	fmov.s	@r15+, fr5\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	fmov.s	@r15+, fr6\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	fmov.s	@r15+, fr7\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	fmov.s	@r15+, fr8\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	fmov.s	@r15+, fr9\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	fmov.s	@r15+, fr10\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	fmov.s	@r15+, fr11\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	lds.l	@r15+, fpscr\n\
-	" CFI_ADJUST_CFA_OFFSET (-4)
-#else
-#define FGR_SAVE	""
-#define FGR_LOAD	""
-#endif
-
-#ifndef PROF
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
-	.text\n\
-	.globl _dl_runtime_resolve\n\
-	.type _dl_runtime_resolve, @function\n\
-	" CFI_STARTPROC "\n\
-	.align 5\n\
-_dl_runtime_resolve:\n\
-	mov.l r2,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r3,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r4,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r5,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r6,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r7,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r12,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	movt r3			! Save T flag.\n\
-	mov.l r3,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	" FGR_SAVE "\n\
-	sts.l pr,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	tst r0,r0\n\
-	bt 1f\n\
-	mov r0,r2\n\
-1:\n\
-	mov r0,r4		! PLT type\n\
-	mov r2,r5		! link map address\n\
-	" FUN_ADDR "\n\
-	jsr @r0			! Call resolver.\n\
-	 mov r1,r6		! reloc offset\n\
-	lds.l @r15+,pr		! Get register content back.\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	" FGR_LOAD "\n\
-	mov.l @r15+,r3\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	shal r3			! Lode T flag.\n\
-	mov.l @r15+,r12\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r7\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r6\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r5\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r4\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r3\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	jmp @r0			! Jump to function address.\n\
-	 mov.l @r15+,r2\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	.align 2\n\
-3:\n\
-	.long " GOTJMP (fixup) "\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
-	.globl _dl_runtime_profile\n\
-	.type _dl_runtime_profile, @function\n\
-	" CFI_STARTPROC "\n\
-	.align 5\n\
-_dl_runtime_profile:\n\
-	mov.l r2,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r3,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r4,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r5,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r6,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r7,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r12,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	movt r3			! Save T flag.\n\
-	mov.l r3,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	" FGR_SAVE "\n\
-	sts.l pr,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	tst r0,r0\n\
-	bt 1f\n\
-	mov r0,r2\n\
-1:\n\
-	mov r0,r4		! PLT type\n\
-	mov r2,r5		! link map address\n\
-	sts pr,r7		! return address\n\
-	" FUN_ADDR "\n\
-	jsr @r0			! Call resolver.\n\
-	 mov r1,r6		! reloc offset\n\
-	lds.l @r15+,pr		! Get register content back.\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	" FGR_LOAD "\n\
-	mov.l @r15+,r3\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	shal r3			! Lode T flag.\n\
-	mov.l @r15+,r12\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r7\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r6\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r5\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r4\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r3\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	jmp @r0			! Jump to function address.\n\
-	 mov.l @r15+,r2\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	.align 2\n\
-3:\n\
-	.long " GOTJMP (profile_fixup) "\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_profile, .-_dl_runtime_profile\n\
-	.previous\n\
-");
-#else
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\
-	.text\n\
-	.globl _dl_runtime_resolve\n\
-	.globl _dl_runtime_profile\n\
-	.type _dl_runtime_resolve, @function\n\
-	.type _dl_runtime_profile, @function\n\
-	.align 5\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
-	mov.l r2,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r3,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r4,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r5,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r6,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r7,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	mov.l r12,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	movt r3			! Save T flag.\n\
-	mov.l r3,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	" FGR_SAVE "\n\
-	sts.l pr,@-r15\n\
-	" CFI_ADJUST_CFA_OFFSET (4) "\n\
-	tst r0,r0\n\
-	bt 1f\n\
-	mov r0,r2\n\
-1:\n\
-	mov r0,r4		! PLT type\n\
-	mov r2,r5		! link map address\n\
-	sts pr,r7		! return address\n\
-	" FUN_ADDR "\n\
-	jsr @r0			! Call resolver.\n\
-	 mov r1,r6		! reloc offset\n\
-	lds.l @r15+,pr		! Get register content back.\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	" FGR_LOAD "\n\
-	mov.l @r15+,r3\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	shal r3			! Lode T flag.\n\
-	mov.l @r15+,r12\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r7\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r6\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r5\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r4\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	mov.l @r15+,r3\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	jmp @r0			! Jump to function address.\n\
-	 mov.l @r15+,r2\n\
-	" CFI_ADJUST_CFA_OFFSET (-4) "\n\
-	.align 2\n\
-3:\n\
-	.long " GOTJMP (fixup) "\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-	.size _dl_runtime_profile, .-_dl_runtime_profile\n\
-	.previous\n\
-");
-#endif
-
 /* Mask identifying addresses reserved for the user program,
    where the dynamic linker should not map anything.  */
 #define ELF_MACHINE_USER_ADDRESS_MASK	0x80000000UL
@@ -459,6 +194,12 @@ _dl_start_user:\n\
 	.long _rtld_local@GOT\n\
 .L_dl_fini:\n\
 	.long _dl_fini@GOT\n\
+	.type __fpscr_values,@object\n\
+	.global __fpscr_values\n\
+__fpscr_values:\n\
+	.long   0\n\
+	.long   0x80000\n\
+	.weak __fpscr_values\n\
 .previous\n\
 ");
 
@@ -510,9 +251,12 @@ elf_machine_plt_value (struct link_map *map, const Elf32_Rela *reloc,
   return value + reloc->r_addend;
 }
 
+#define ARCH_LA_PLTENTER sh_gnu_pltenter
+#define ARCH_LA_PLTEXIT sh_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* SH never uses Elf32_Rel relocations.	 */
 #define ELF_MACHINE_NO_REL 1
@@ -579,18 +323,9 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
   else
     {
       const Elf32_Sym *const refsym = sym;
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
 
-      value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
-#else
-
-      value = RESOLVE (&sym, version, r_type);
-# ifndef RTLD_BOOTSTRAP
-      if (sym != NULL)
-# endif
-	value += sym->st_value;
-#endif
+      value = sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value;
       value += reloc->r_addend;
 
       switch (r_type)
@@ -736,4 +471,4 @@ elf_machine_lazy_rel (struct link_map *map,
     _dl_reloc_bad_type (map, ELF32_R_TYPE (reloc->r_info), 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/sh/dl-trampoline.S b/sysdeps/sh/dl-trampoline.S
new file mode 100644
index 0000000000..79493d50b9
--- /dev/null
+++ b/sysdeps/sh/dl-trampoline.S
@@ -0,0 +1,431 @@
+/* PLT trampolines.  SH version.
+   Copyright (C) 2005 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 <sysdep.h>
+
+	.text
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve, @function
+	cfi_startproc
+	.align 5
+_dl_runtime_resolve:
+	mov.l r2,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r3,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r4,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r5,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r6,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r7,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r12,@-r15
+	cfi_adjust_cfa_offset (4)
+	sts.l macl,@-r15
+	cfi_adjust_cfa_offset (4)
+	sts.l mach,@-r15
+	cfi_adjust_cfa_offset (4)
+	movt r3			! Save T flag.
+	mov.l r3,@-r15
+	cfi_adjust_cfa_offset (4)
+#ifdef HAVE_FPU
+	sts.l	fpscr,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov	#8,r3
+	swap.w	r3,r3
+	lds	r3,fpscr
+	fmov.s	fr11,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr10,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr9,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr8,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr7,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr6,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr5,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr4,@-r15
+	cfi_adjust_cfa_offset (4)
+#endif
+	sts.l pr,@-r15
+	cfi_adjust_cfa_offset (4)
+	tst r0,r0
+	bt 1f
+	mov r0,r2
+1:
+	mov r0,r4		! PLT type
+	mov r2,r5		! link map address
+#ifdef SHARED
+	mov.l 2f,r2
+	mova 2f,r0
+	add r0,r2		! Get GOT address in r2
+	mov.l 3f,r0
+	add r2,r0
+#else
+	mov.l 3f,r0
+#endif
+	jsr @r0			! Call resolver.
+	 mov r1,r6		! reloc offset
+	lds.l @r15+,pr		! Get register content back.
+	cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+	fmov.s	@r15+,fr4
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr5
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr6
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr7
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr8
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr9
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr10
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr11
+	cfi_adjust_cfa_offset (-4)
+	lds.l	@r15+,fpscr
+	cfi_adjust_cfa_offset (-4)
+#endif
+	mov.l @r15+,r3
+	cfi_adjust_cfa_offset (-4)
+	shal r3			! Lode T flag.
+	lds.l @r15+,mach
+	cfi_adjust_cfa_offset (-4)
+	lds.l @r15+,macl
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r12
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r7
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r6
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r5
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r4
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r3
+	cfi_adjust_cfa_offset (-4)
+	jmp @r0			! Jump to function address.
+	 mov.l @r15+,r2
+	cfi_adjust_cfa_offset (-4)
+	.align 2
+#ifdef SHARED
+2:	.long _GLOBAL_OFFSET_TABLE_
+3:	.long _dl_fixup@GOTOFF
+#else
+3:	.long _dl_fixup
+#endif
+	cfi_endproc
+	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile,@function
+	cfi_startproc
+	.align 5
+_dl_runtime_profile:
+	mov.l r12,@-r15
+	cfi_adjust_cfa_offset (4)
+#ifdef HAVE_FPU
+	sts.l	fpscr,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov	#8,r12
+	swap.w	r12,r12
+	lds	r12,fpscr
+	fmov.s	fr11,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr10,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr9,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr8,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr7,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr6,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr5,@-r15
+	cfi_adjust_cfa_offset (4)
+	fmov.s	fr4,@-r15
+	cfi_adjust_cfa_offset (4)
+#else
+	add #-36,r15
+	cfi_adjust_cfa_offset (36)
+#endif
+	mov.l r7,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r6,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r5,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r4,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r3,@-r15
+	cfi_adjust_cfa_offset (4)
+	mov.l r2,@-r15
+	cfi_adjust_cfa_offset (4)
+	sts.l macl,@-r15
+	cfi_adjust_cfa_offset (4)
+	sts.l mach,@-r15
+	cfi_adjust_cfa_offset (4)
+	movt r3			! Save T flag.
+	mov.l r3,@-r15
+	cfi_adjust_cfa_offset (4)
+	sts.l pr,@-r15
+	cfi_adjust_cfa_offset (4)
+	tst r0,r0
+	bt 1f
+	mov r0,r2
+1:
+	mov r0,r4		! PLT type
+	mov r2,r5		! link map address
+	sts pr,r7		! return address
+	add #-24,r15
+	cfi_adjust_cfa_offset (24)
+	mov #40,r0
+	add r15,r0
+	mov.l r0,@r15		! Address of the register structure
+	mov #-1,r0
+	mov.l r0,@(8,r15)
+	mov #8,r0
+	add r15,r0
+	mov.l r0,@(4,r15)
+	mov.l r5,@(12,r15)
+	mov.l r1,@(16,r15)
+#ifdef SHARED
+	mov.l 2f,r12
+	mova 2f,r0
+	add r0,r12		! Get GOT address in r12
+	mov.l 3f,r0
+	add r12,r0
+#else
+	mov.l 3f,r0
+#endif
+	jsr @r0			! Call resolver.
+	 mov r1,r6		! reloc offset
+	mov.l @(8,r15),r1
+	cmp/pz r1
+	bt 4f
+	add #24,r15
+	cfi_adjust_cfa_offset (-24)
+	lds.l @r15+,pr		! Get register content back.
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r3
+	cfi_adjust_cfa_offset (-4)
+	shal r3			! Lode T flag.
+	lds.l @r15+,mach
+	cfi_adjust_cfa_offset (-4)
+	lds.l @r15+,macl
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r2
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r3
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r4
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r5
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r6
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r7
+	cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+	fmov.s	@r15+,fr4
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr5
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr6
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr7
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr8
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr9
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr10
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr11
+	cfi_adjust_cfa_offset (-4)
+	lds.l	@r15+,fpscr
+	cfi_adjust_cfa_offset (-4)
+#else
+	add #36,r15
+	cfi_adjust_cfa_offset (-36)
+#endif
+	jmp @r0			! Jump to function address.
+	 mov.l @r15+,r12
+	cfi_adjust_cfa_offset (-4)
+	.align 2
+#ifdef SHARED
+2:	.long _GLOBAL_OFFSET_TABLE_
+3:	.long _dl_profile_fixup@GOTOFF
+#else
+3:	.long _dl_profile_fixup
+#endif
+
+	cfi_adjust_cfa_offset (104)
+4:
+	mov #104,r3
+	add r15,r3		! Original stack
+	mov.l r8,@(20,r15)
+	cfi_rel_offset (r8, 20)
+	mov r15,r8
+	sub r1,r15
+	shlr2 r15
+	shll2 r15
+	mov r15,r4
+	shlr2 r1
+	tst r1,r1
+5:	
+	bt/s 6f
+	 dt r1
+	mov.l @r3+,r2
+	mov.l r2,@r4
+	bra 5b
+	 add #4,r4
+6:
+	mov.l @r8,r12
+	mov.l @r12+,r2
+	mov.l @r12+,r3
+	mov.l @r12+,r4
+	mov.l @r12+,r5
+	mov.l @r12+,r6
+	mov.l @r12+,r7
+#ifdef HAVE_FPU
+	fmov.s	@r12+,fr4
+	fmov.s	@r12+,fr5
+	fmov.s	@r12+,fr6
+	fmov.s	@r12+,fr7
+	fmov.s	@r12+,fr8
+	fmov.s	@r12+,fr9
+	fmov.s	@r12+,fr10
+	fmov.s	@r12+,fr11
+	lds.l	@r12+,fpscr
+#else
+	add #36,r2
+#endif
+	jsr @r0			! Call function.
+	 nop
+	mov r8,r15
+	mov.l @(12,r15),r4	! link map address
+	mov.l @(16,r15),r5	! reloc offset
+	mov.l @r15,r6		! input registers
+#ifdef HAVE_FPU
+	mov #16,r8
+	add r15,r8
+	fmov.s fr1,@-r8
+	fmov.s fr0,@-r8
+#else
+	mov #8,r8
+	add r15,r8
+#endif
+	mov.l r1,@-r8
+	mov.l r0,@-r8
+	mov.l @(20,r15),r8
+	cfi_restore (r8)
+#ifdef SHARED
+	mov.l 7f,r12
+	mova 7f,r0
+	add r0,r12		! Get GOT address in r12
+	mov.l 8f,r0
+	add r12,r0
+#else
+	mov.l 8f,r0
+#endif
+	jsr @r0
+	 mov r15,r7		! output registers
+	mov.l @r15+,r0
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r1
+	cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+	fmov.s @r15+,fr0
+	cfi_adjust_cfa_offset (-4)
+	fmov.s @r15+,fr1
+	cfi_adjust_cfa_offset (-4)
+	add #8,r15
+	cfi_adjust_cfa_offset (-8)
+#else
+	add #16,r15
+	cfi_adjust_cfa_offset (-16)
+#endif
+	lds.l @r15+,pr		! Get register content back.
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r3
+	cfi_adjust_cfa_offset (-4)
+	shal r3			! Lode T flag.
+	lds.l @r15+,mach
+	cfi_adjust_cfa_offset (-4)
+	lds.l @r15+,macl
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r2
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r3
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r4
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r5
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r6
+	cfi_adjust_cfa_offset (-4)
+	mov.l @r15+,r7
+	cfi_adjust_cfa_offset (-4)
+#ifdef HAVE_FPU
+	fmov.s	@r15+,fr4
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr5
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr6
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr7
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr8
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr9
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr10
+	cfi_adjust_cfa_offset (-4)
+	fmov.s	@r15+,fr11
+	cfi_adjust_cfa_offset (-4)
+	lds.l	@r15+,fpscr
+	cfi_adjust_cfa_offset (-4)
+#else
+	add #36,r15
+	cfi_adjust_cfa_offset (-36)
+#endif
+	rts			! Jump to function address.
+	 mov.l @r15+,r12
+	cfi_adjust_cfa_offset (-4)
+	cfi_endproc
+	.align 2
+#ifdef SHARED
+7:	.long _GLOBAL_OFFSET_TABLE_
+8:	.long _dl_call_pltexit@GOTOFF
+#else
+8:	.long _dl_call_pltexit
+#endif
+	.size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/sh/sh4/Versions b/sysdeps/sh/sh4/Versions
new file mode 100644
index 0000000000..8cc1c7b7d4
--- /dev/null
+++ b/sysdeps/sh/sh4/Versions
@@ -0,0 +1,5 @@
+ld {
+  GLIBC_PRIVATE {
+    __fpscr_values;
+  }
+}
diff --git a/sysdeps/sh/sh4/dl-machine.h b/sysdeps/sh/sh4/dl-machine.h
deleted file mode 100644
index ec9f6f7b45..0000000000
--- a/sysdeps/sh/sh4/dl-machine.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#define HAVE_FPU
-#include <sysdeps/sh/dl-machine.h>
diff --git a/sysdeps/sh/sh4/dl-trampoline.S b/sysdeps/sh/sh4/dl-trampoline.S
new file mode 100644
index 0000000000..f9529851a1
--- /dev/null
+++ b/sysdeps/sh/sh4/dl-trampoline.S
@@ -0,0 +1,2 @@
+#define HAVE_FPU
+#include <sysdeps/sh/dl-trampoline.S>
diff --git a/sysdeps/unix/i386/sysdep.S b/sysdeps/unix/i386/sysdep.S
index 6056cbeef2..3bc872add8 100644
--- a/sysdeps/unix/i386/sysdep.S
+++ b/sysdeps/unix/i386/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 2000, 2002, 2004
+/* Copyright (C) 1991,1992,1993,1994,1995,1996,1997,2000,2002,2004,2005
 	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -47,7 +47,12 @@ notb:
 #endif
 #ifndef	PIC
 # if USE___THREAD
+#  ifndef NO_TLS_DIRECT_SEG_REFS
 	movl %eax, %gs:C_SYMBOL_NAME(errno@NTPOFF)
+#  else
+	movl %gs:0, %ecx
+	movl %eax, C_SYMBOL_NAME(errno@NTPOFF)(%ecx)
+#  endif
 # elif !defined _LIBC_REENTRANT
 	movl %eax, C_SYMBOL_NAME(errno)
 # else
@@ -66,7 +71,12 @@ notb:
 
 	/* Pop %ebx value saved before jumping here.  */
 	popl %ebx
+#  ifndef NO_TLS_DIRECT_SEG_REFS
+	addl %gs:0, %ecx
+	movl %eax, (%ecx)
+#  else
 	movl %eax, %gs:0(%ecx)
+#  endif
 # elif RTLD_PRIVATE_ERRNO
 	movl %eax, C_SYMBOL_NAME(rtld_errno@GOTOFF)(%ebx)
 
diff --git a/sysdeps/unix/rewinddir.c b/sysdeps/unix/rewinddir.c
index 9f3724fc6a..051e93595e 100644
--- a/sysdeps/unix/rewinddir.c
+++ b/sysdeps/unix/rewinddir.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1995-1998, 2005 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
@@ -30,6 +30,7 @@ rewinddir (dirp)
 {
   __libc_lock_lock (dirp->lock);
   (void) __lseek (dirp->fd, (off_t) 0, SEEK_SET);
+  dirp->filepos = 0;
   dirp->offset = 0;
   dirp->size = 0;
   __libc_lock_unlock (dirp->lock);
diff --git a/sysdeps/unix/sysv/linux/alpha/oldglob.c b/sysdeps/unix/sysv/linux/alpha/oldglob.c
index 9d39176f6b..6d9b79f2c3 100644
--- a/sysdeps/unix/sysv/linux/alpha/oldglob.c
+++ b/sysdeps/unix/sysv/linux/alpha/oldglob.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 2000, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 2000, 2004, 2005 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
@@ -91,6 +91,7 @@ __old_globfree (old_glob_t *pglob)
   /* We only need these two symbols.  */
   correct.gl_pathc = pglob->gl_pathc;
   correct.gl_pathv = pglob->gl_pathv;
+  correct.gl_offs = pglob->gl_offs;
 
   globfree (&correct);
 }
diff --git a/sysdeps/unix/sysv/linux/dl-execstack.c b/sysdeps/unix/sysv/linux/dl-execstack.c
index 6ef9679045..b38d0c4238 100644
--- a/sysdeps/unix/sysv/linux/dl-execstack.c
+++ b/sysdeps/unix/sysv/linux/dl-execstack.c
@@ -1,5 +1,5 @@
 /* Stack executability handling for GNU dynamic linker.  Linux version.
-   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005 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
@@ -24,6 +24,7 @@
 #include <stdbool.h>
 #include <stackinfo.h>
 #include <caller.h>
+#include <sysdep.h>
 
 #include "kernel-features.h"
 
@@ -38,6 +39,7 @@ _dl_make_stack_executable (void **stack_endp)
   /* This gives us the highest/lowest page that needs to be changed.  */
   uintptr_t page = ((uintptr_t) *stack_endp
 		    & -(intptr_t) GLRO(dl_pagesize));
+  int result = 0;
 
   /* Challenge the caller.  */
   if (__builtin_expect (__check_caller (RETURN_ADDRESS (0),
@@ -60,7 +62,10 @@ _dl_make_stack_executable (void **stack_endp)
 	no_growsupdown = true;
       else
 # endif
-	return errno;
+	{
+	  result = errno;
+	  goto out;
+	}
     }
 #endif
 
@@ -85,7 +90,10 @@ _dl_make_stack_executable (void **stack_endp)
       else
 	{
 	  if (errno != ENOMEM)	/* Unexpected failure mode.  */
-	    return errno;
+	    {
+	      result = errno;
+	      goto out;
+	    }
 
 	  if (size == GLRO(dl_pagesize))
 	    /* We just tried to mprotect the top hole page and failed.
@@ -108,7 +116,10 @@ _dl_make_stack_executable (void **stack_endp)
       else
 	{
 	  if (errno != ENOMEM)	/* Unexpected failure mode.  */
-	    return errno;
+	    {
+	      result = errno;
+	      goto out;
+	    }
 
 	  if (size == GLRO(dl_pagesize))
 	    /* We just tried to mprotect the lowest hole page and failed.
@@ -133,6 +144,11 @@ _dl_make_stack_executable (void **stack_endp)
   /* Remember that we changed the permission.  */
   GL(dl_stack_flags) |= PF_X;
 
-  return 0;
+ out:
+#ifdef check_consistency
+  check_consistency ();
+#endif
+
+  return result;
 }
 rtld_hidden_def (_dl_make_stack_executable)
diff --git a/sysdeps/unix/sysv/linux/futimes.c b/sysdeps/unix/sysv/linux/futimes.c
index f43f568ec1..0c4be2b67f 100644
--- a/sysdeps/unix/sysv/linux/futimes.c
+++ b/sysdeps/unix/sysv/linux/futimes.c
@@ -1,5 +1,5 @@
 /* futimes -- change access and modification times of open file.  Linux version.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2005 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
@@ -23,6 +23,7 @@
 #include <utime.h>
 #include <sys/time.h>
 #include <stdio-common/_itoa.h>
+#include <fcntl.h>
 
 #include "kernel-features.h"
 
@@ -40,31 +41,58 @@ __futimes (int fd, const struct timeval tvp[2])
   char *cp = _itoa_word ((unsigned int) fd, fname + sizeof (fname) - 1, 10, 0);
   cp = memcpy (cp - sizeof (selffd) + 1, selffd, sizeof (selffd) - 1);
 
+  int result;
 #ifdef __NR_utimes
-  int result = INLINE_SYSCALL (utimes, 2, cp, tvp);
+  result = INLINE_SYSCALL (utimes, 2, cp, tvp);
 # ifndef __ASSUME_UTIMES
-  if (result != -1 || errno != ENOSYS)
+  if (result == -1 && errno == ENOSYS)
 # endif
-    return result;
 #endif
-
-  /* The utimes() syscall does not exist or is not available in the
-     used kernel.  Use utime().  For this we have to convert to the
-     data format utime() expects.  */
+    {
+      /* The utimes() syscall does not exist or is not available in the
+	 used kernel.  Use utime().  For this we have to convert to the
+	 data format utime() expects.  */
 #ifndef __ASSUME_UTIMES
-  struct utimbuf buf;
-  struct utimbuf *times;
+      struct utimbuf buf;
+      struct utimbuf *times;
 
-  if (tvp != NULL)
-    {
-      times = &buf;
-      buf.actime = tvp[0].tv_sec + (tvp[0].tv_usec + 500000) / 1000000;
-      buf.modtime = tvp[1].tv_sec + (tvp[1].tv_usec + 500000) / 1000000;
-    }
-  else
-    times = NULL;
+      if (tvp != NULL)
+	{
+	  times = &buf;
+	  buf.actime = tvp[0].tv_sec + (tvp[0].tv_usec + 500000) / 1000000;
+	  buf.modtime = tvp[1].tv_sec + (tvp[1].tv_usec + 500000) / 1000000;
+	}
+      else
+	times = NULL;
 
-  return INLINE_SYSCALL (utime, 2, cp, times);
+      result = INLINE_SYSCALL (utime, 2, cp, times);
 #endif
+    }
+
+  if (result == -1)
+    /* Check for errors that result from failing to find /proc.
+       This means we can't do futimes at all, so return ENOSYS
+       rather than some confusing error.  */
+    switch (errno)
+      {
+      case EACCES:
+	if (tvp == NULL)  /* Could be a path problem or a file problem.  */
+	  break;
+	/*FALLTHROUGH*/
+      case ELOOP:
+      case ENAMETOOLONG:
+      case ENOTDIR:
+	__set_errno (ENOSYS);
+	break;
+
+      case ENOENT:
+	/* Validate the file descriptor by letting fcntl set errno to
+	   EBADF if it's bogus.  Otherwise it's a /proc issue.  */
+	if (INLINE_SYSCALL (fcntl, 3, fd, F_GETFD, 0) != -1)
+	  __set_errno (ENOSYS);
+	break;
+      }
+
+  return result;
 }
 weak_alias (__futimes, futimes)
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index af75d4c51a..6bea9d2044 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -1,5 +1,5 @@
-/* Copyright (C) 1992,1993,1995-2000,2002,2003,2004
-   Free Software Foundation, Inc.
+/* Copyright (C) 1992,1993,1995,1996,1997,1998,1999,2000,2002,2003,2004,2005
+   	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper, <drepper@gnu.org>, August 1995.
 
@@ -154,9 +154,17 @@ __i686.get_pc_thunk.reg:						      \
   movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx;			      \
   xorl %edx, %edx;							      \
   subl %eax, %edx;							      \
-  movl %edx, %gs:0(%ecx);						      \
+  SYSCALL_ERROR_HANDLER_TLS_STORE (%edx, %ecx);				      \
   orl $-1, %eax;							      \
   jmp L(pseudo_end);
+#   ifndef NO_TLS_DIRECT_SEG_REFS
+#    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)		      \
+  movl src, %gs:(destoff)
+#   else
+#    define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff)		      \
+  addl %gs:0, destoff;							      \
+  movl src, (destoff)
+#   endif
 #  else
 #   define SYSCALL_ERROR_HANDLER					      \
 0:pushl %ebx;								      \
@@ -532,6 +540,29 @@ asm (".L__X'%ebx = 1\n\t"
 # define EXTRAVAR_5
 #endif
 
+/* Consistency check for position-independent code.  */
+#ifdef __PIC__
+# define check_consistency()						      \
+  ({ int __res;								      \
+     __asm__ __volatile__						      \
+       ("call __i686.get_pc_thunk.cx;"					      \
+	"addl $_GLOBAL_OFFSET_TABLE_, %%ecx;"				      \
+	"subl %%ebx, %%ecx;"						      \
+	"je 1f;"							      \
+	"ud2;"								      \
+	"1:\n"								      \
+	".section .gnu.linkonce.t.__i686.get_pc_thunk.cx,\"ax\",@progbits;"   \
+	".globl __i686.get_pc_thunk.cx;"				      \
+	".hidden __i686.get_pc_thunk.cx;"				      \
+	".type __i686.get_pc_thunk.cx,@function;"			      \
+	"__i686.get_pc_thunk.cx:"					      \
+	"movl (%%esp), %%ecx;"						      \
+	"ret;"								      \
+	".previous"							      \
+	: "=c" (__res));						      \
+     __res; })
+#endif
+
 #endif	/* __ASSEMBLER__ */
 
 #endif /* linux/i386/sysdep.h */
diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c
index 7f0b963cb7..b061a848c6 100644
--- a/sysdeps/unix/sysv/linux/init-first.c
+++ b/sysdeps/unix/sysv/linux/init-first.c
@@ -40,7 +40,6 @@ char **__libc_argv attribute_hidden;
 
 
 void
-attribute_hidden
 __libc_init_first (int argc, char **argv, char **envp)
 {
 #ifdef SHARED
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index f499a712c4..83ebe0cf74 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -1,6 +1,6 @@
 /* Set flags signalling availability of kernel features based on given
    kernel version number.
-   Copyright (C) 1999-2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999-2003, 2004, 2005 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
@@ -79,6 +79,11 @@
 # define __ASSUME_SIOCGIFNAME		1
 #endif
 
+/* MSG_NOSIGNAL was at least available with Linux 2.2.0.  */
+#if __LINUX_KERNEL_VERSION >= 131584
+# define __ASSUME_MSG_NOSIGNAL		1
+#endif
+
 /* On x86 another `getrlimit' syscall was added in 2.3.25.  */
 #if __LINUX_KERNEL_VERSION >= 131865 && defined __i386__
 # define __ASSUME_NEW_GETRLIMIT_SYSCALL	1
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
index 6514f442a6..7eaaad20a4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/setcontext.S
@@ -1,5 +1,5 @@
 /* Switch to context.
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2005 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
@@ -47,7 +47,7 @@ ENTRY(__novec_setcontext)
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  ld	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne	  L(nv_do_sigret)
 
@@ -104,7 +104,7 @@ ENTRY(__novec_setcontext)
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
+  mtcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
@@ -213,7 +213,7 @@ ENTRY(__setcontext)
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  ld	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne	  L(do_sigret)
 
@@ -380,11 +380,11 @@ L(has_no_vec):
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
+  mtcr r0
   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S b/sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S
index f99df951a2..772adacfe4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/swapcontext.S
@@ -1,5 +1,5 @@
 /* Save current context and install the given one.
-   Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2005 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
@@ -150,7 +150,7 @@ ENTRY(__novec_swapcontext)
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  ld	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne	  L(nv_do_sigret)
 
@@ -199,7 +199,7 @@ ENTRY(__novec_swapcontext)
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
+  mtcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
@@ -521,7 +521,7 @@ L(has_no_vec):
  * of a procedure call (makecontext), so we don't need to restore
  * msr and ctr.  We don't restore r13 since it will be used as
  * the TLS pointer.  */
-  lwz	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
+  ld	  r0,(SIGCONTEXT_GP_REGS+(PT_MSR*8))(r31)
   cmpdi r0,0
   bne	  L(do_sigret)
 
@@ -681,11 +681,11 @@ L(has_no_vec2):
   ld   r4,(SIGCONTEXT_GP_REGS+(PT_R4*8))(r31)
   ld   r0,(SIGCONTEXT_GP_REGS+(PT_CCR*8))(r31)
   ld   r5,(SIGCONTEXT_GP_REGS+(PT_R5*8))(r31)
-  mfcr r0
   ld   r6,(SIGCONTEXT_GP_REGS+(PT_R6*8))(r31)
   ld   r7,(SIGCONTEXT_GP_REGS+(PT_R7*8))(r31)
   ld   r8,(SIGCONTEXT_GP_REGS+(PT_R8*8))(r31)
   ld   r9,(SIGCONTEXT_GP_REGS+(PT_R9*8))(r31)
+  mtcr r0
   ld   r10,(SIGCONTEXT_GP_REGS+(PT_R10*8))(r31)
   ld   r11,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r31)
   ld   r12,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r31)
diff --git a/sysdeps/unix/sysv/linux/syslog.c b/sysdeps/unix/sysv/linux/syslog.c
new file mode 100644
index 0000000000..eaaa9839dc
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/syslog.c
@@ -0,0 +1,10 @@
+#include "kernel-features.h"
+
+#if __ASSUME_MSG_NOSIGNAL
+# define NO_SIGPIPE
+# define send_flags MSG_NOSIGNAL
+#else
+# define send_flags 0
+#endif
+
+#include <sysdeps/generic/syslog.c>
diff --git a/sysdeps/x86_64/bits/link.h b/sysdeps/x86_64/bits/link.h
index 8ea7157156..2890c2d88d 100644
--- a/sysdeps/x86_64/bits/link.h
+++ b/sysdeps/x86_64/bits/link.h
@@ -1,14 +1,117 @@
-#if __WORDSIZE == 64
-struct link_map_machine
-  {
-    Elf64_Addr plt; /* Address of .plt + 0x16 */
-    Elf64_Addr gotplt; /* Address of .got + 0x18 */
-  };
+/* Copyright (C) 2004, 2005 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	_LINK_H
+# error "Never include <bits/link.h> directly; use <link.h> instead."
+#endif
+
+
+#if __ELF_NATIVE_CLASS == 32
+/* Registers for entry into PLT on IA-32.  */
+typedef struct La_i86_regs
+{
+  uint32_t lr_edx;
+  uint32_t lr_ecx;
+  uint32_t lr_eax;
+  uint32_t lr_ebp;
+  uint32_t lr_esp;
+} La_i86_regs;
+
+/* Return values for calls from PLT on IA-32.  */
+typedef struct La_i86_retval
+{
+  uint32_t lrv_eax;
+  uint32_t lrv_edx;
+  long double lrv_st0;
+  long double lrv_st1;
+} La_i86_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf32_Addr la_i86_gnu_pltenter (Elf32_Sym *__sym, unsigned int __ndx,
+				       uintptr_t *__refcook,
+				       uintptr_t *__defcook,
+				       La_i86_regs *__regs,
+				       unsigned int *__flags,
+				       const char *__symname,
+				       long int *__framesizep);
+extern unsigned int la_i86_gnu_pltexit (Elf32_Sym *__sym, unsigned int __ndx,
+					uintptr_t *__refcook,
+					uintptr_t *__defcook,
+					const La_i86_regs *__inregs,
+					La_i86_retval *__outregs,
+					const char *symname);
+
+__END_DECLS
 
 #else
-struct link_map_machine
-  {
-    Elf32_Addr plt; /* Address of .plt + 0x16 */
-    Elf32_Addr gotplt; /* Address of .got + 0x0c */
-  };
+
+/* Registers for entry into PLT on x86-64.  */
+# if __GNUC_PREREQ (4,0)
+typedef float La_x86_64_xmm __attribute__ ((__vector_size__ (16)));
+# else
+typedef float La_x86_64_xmm __attribute__ ((__mode__ (__V4SF__)));
+# endif
+
+typedef struct La_x86_64_regs
+{
+  uint64_t lr_rdx;
+  uint64_t lr_r8;
+  uint64_t lr_r9;
+  uint64_t lr_rcx;
+  uint64_t lr_rsi;
+  uint64_t lr_rdi;
+  uint64_t lr_rbp;
+  uint64_t lr_rsp;
+  La_x86_64_xmm lr_xmm[8];
+} La_x86_64_regs;
+
+/* Return values for calls from PLT on x86-64.  */
+typedef struct La_x86_64_retval
+{
+  uint64_t lrv_rax;
+  uint64_t lrv_rdx;
+  La_x86_64_xmm lrv_xmm0;
+  La_x86_64_xmm lrv_xmm1;
+  long double lrv_st0;
+  long double lrv_st1;
+} La_x86_64_retval;
+
+
+__BEGIN_DECLS
+
+extern Elf64_Addr la_x86_64_gnu_pltenter (Elf64_Sym *__sym,
+					  unsigned int __ndx,
+					  uintptr_t *__refcook,
+					  uintptr_t *__defcook,
+					  La_x86_64_regs *__regs,
+					  unsigned int *__flags,
+					  const char *__symname,
+					  long int *__framesizep);
+extern unsigned int la_x86_64_gnu_pltexit (Elf64_Sym *__sym,
+					   unsigned int __ndx,
+					   uintptr_t *__refcook,
+					   uintptr_t *__defcook,
+					   const La_x86_64_regs *__inregs,
+					   La_x86_64_retval *__outregs,
+					   const char *symname);
+
+__END_DECLS
+
 #endif
diff --git a/sysdeps/x86_64/bits/linkmap.h b/sysdeps/x86_64/bits/linkmap.h
new file mode 100644
index 0000000000..8ea7157156
--- /dev/null
+++ b/sysdeps/x86_64/bits/linkmap.h
@@ -0,0 +1,14 @@
+#if __WORDSIZE == 64
+struct link_map_machine
+  {
+    Elf64_Addr plt; /* Address of .plt + 0x16 */
+    Elf64_Addr gotplt; /* Address of .got + 0x18 */
+  };
+
+#else
+struct link_map_machine
+  {
+    Elf32_Addr plt; /* Address of .plt + 0x16 */
+    Elf32_Addr gotplt; /* Address of .got + 0x0c */
+  };
+#endif
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index b932f51d15..bb0c77fd0b 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  x86-64 version.
-   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Andreas Jaeger <aj@suse.de>.
 
@@ -116,7 +116,8 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
 	{
 	  got[2] = (Elf64_Addr) &_dl_runtime_profile;
 
-	  if (_dl_name_match_p (GLRO(dl_profile), l))
+	  if (GLRO(dl_profile) != NULL
+	      && _dl_name_match_p (GLRO(dl_profile), l))
 	    /* This is the object we are looking for.  Say that we really
 	       want profiling and the timers are started.  */
 	    GL(dl_profile_map) = l;
@@ -130,128 +131,6 @@ elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
   return lazy;
 }
 
-/* This code is used in dl-runtime.c to call the `fixup' function
-   and then redirect to the address it returns.  */
-#ifndef PROF
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
-	.text\n\
-	.globl _dl_runtime_resolve\n\
-	.type _dl_runtime_resolve, @function\n\
-	.align 16\n\
-	" CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-	subq $56,%rsp\n\
-	" CFI_ADJUST_CFA_OFFSET(72)" # Incorporate PLT\n\
-	movq %rax,(%rsp)	# Preserve registers otherwise clobbered.\n\
-	movq %rcx,8(%rsp)\n\
-	movq %rdx,16(%rsp)\n\
-	movq %rsi,24(%rsp)\n\
-	movq %rdi,32(%rsp)\n\
-	movq %r8,40(%rsp)\n\
-	movq %r9,48(%rsp)\n\
-	movq 64(%rsp), %rsi	# Copy args pushed by PLT in register.\n\
-	movq %rsi,%r11		# Multiply by 24\n\
-	addq %r11,%rsi\n\
-	addq %r11,%rsi\n\
-	shlq $3, %rsi\n\
-	movq 56(%rsp), %rdi	# %rdi: link_map, %rsi: reloc_offset\n\
-	call fixup		# Call resolver.\n\
-	movq %rax, %r11		# Save return value\n\
-	movq 48(%rsp),%r9	# Get register content back.\n\
-	movq 40(%rsp),%r8\n\
-	movq 32(%rsp),%rdi\n\
-	movq 24(%rsp),%rsi\n\
-	movq 16(%rsp),%rdx\n\
-	movq 8(%rsp),%rcx\n\
-	movq (%rsp),%rax\n\
-	addq $72,%rsp		# Adjust stack(PLT did 2 pushes)\n\
-	" CFI_ADJUST_CFA_OFFSET(-72)" \n\
-	jmp *%r11		# Jump to function address.\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-\n\
-	.globl _dl_runtime_profile\n\
-	.type _dl_runtime_profile, @function\n\
-	.align 16\n\
-	" CFI_STARTPROC "\n\
-_dl_runtime_profile:\n\
-	subq $56,%rsp\n\
-	" CFI_ADJUST_CFA_OFFSET(72)" # Incorporate PLT\n\
-	movq %rax,(%rsp)	# Preserve registers otherwise clobbered.\n\
-	movq %rcx,8(%rsp)\n\
-	movq %rdx,16(%rsp)\n\
-	movq %rsi,24(%rsp)\n\
-	movq %rdi,32(%rsp)\n\
-	movq %r8,40(%rsp)\n\
-	movq %r9,48(%rsp)\n\
-	movq 72(%rsp), %rdx	# Load return address if needed\n\
-	movq 64(%rsp), %rsi	# Copy args pushed by PLT in register.\n\
-	movq %rsi,%r11		# Multiply by 24\n\
-	addq %r11,%rsi\n\
-	addq %r11,%rsi\n\
-	shlq $3, %rsi\n\
-	movq 56(%rsp), %rdi	# %rdi: link_map, %rsi: reloc_offset\n\
-	call profile_fixup	# Call resolver.\n\
-	movq %rax, %r11		# Save return value\n\
-	movq 48(%rsp),%r9	# Get register content back.\n\
-	movq 40(%rsp),%r8\n\
-	movq 32(%rsp),%rdi\n\
-	movq 24(%rsp),%rsi\n\
-	movq 16(%rsp),%rdx\n\
-	movq 8(%rsp),%rcx\n\
-	movq (%rsp),%rax\n\
-	addq $72,%rsp		# Adjust stack\n\
-	" CFI_ADJUST_CFA_OFFSET(-72)"\n\
-	jmp *%r11		# Jump to function address.\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_profile, .-_dl_runtime_profile\n\
-	.previous\n\
-");
-#else
-# define ELF_MACHINE_RUNTIME_TRAMPOLINE asm ("\n\
-	.text\n\
-	.globl _dl_runtime_resolve\n\
-	.globl _dl_runtime_profile\n\
-	.type _dl_runtime_resolve, @function\n\
-	.type _dl_runtime_profile, @function\n\
-	.align 16\n\
-	" CFI_STARTPROC "\n\
-_dl_runtime_resolve:\n\
-_dl_runtime_profile:\n\
-	subq $56,%rsp\n\
-	" CFI_ADJUST_CFA_OFFSET(72)" # Incorporate PLT\n\
-	movq %rax,(%rsp)	# Preserve registers otherwise clobbered.\n\
-	movq %rcx,8(%rsp)\n\
-	movq %rdx,16(%rsp)\n\
-	movq %rsi,24(%rsp)\n\
-	movq %rdi,32(%rsp)\n\
-	movq %r8,40(%rsp)\n\
-	movq %r9,48(%rsp)\n\
-	movq 64(%rsp), %rsi	# Copy args pushed by PLT in register.\n\
-	movq %rsi,%r11		# Multiply by 24\n\
-	addq %r11,%rsi\n\
-	addq %r11,%rsi\n\
-	shlq $3, %rsi\n\
-	movq 56(%rsp), %rdi	# %rdi: link_map, %rsi: reloc_offset\n\
-	call fixup		# Call resolver.\n\
-	movq %rax, %r11		# Save return value\n\
-	movq 48(%rsp),%r9	# Get register content back.\n\
-	movq 40(%rsp),%r8\n\
-	movq 32(%rsp),%rdi\n\
-	movq 24(%rsp),%rsi\n\
-	movq 16(%rsp),%rdx\n\
-	movq 8(%rsp),%rcx\n\
-	movq (%rsp),%rax\n\
-	addq $72,%rsp		# Adjust stack\n\
-	" CFI_ADJUST_CFA_OFFSET(-72)"\n\
-	jmp *%r11		# Jump to function address.\n\
-	" CFI_ENDPROC "\n\
-	.size _dl_runtime_resolve, .-_dl_runtime_resolve\n\
-	.size _dl_runtime_profile, .-_dl_runtime_profile\n\
-	.previous\n\
-");
-#endif
-
 /* Initial entry point code for the dynamic linker.
    The C function `_dl_start' is the real entry point;
    its return value is the user program's entry point.  */
@@ -280,16 +159,24 @@ _dl_start_user:\n\
 	# Call _dl_init (struct link_map *main_map, int argc, char **argv, char **env)\n\
 	# argc -> rsi\n\
 	movq %rdx, %rsi\n\
+	# Save %rsp value in %r13.\n\
+	movq %rsp, %r13\n\
+	# And align stack for the _dl_init_internal call. \n\
+	andq $-16, %rsp\n\
 	# _dl_loaded -> rdi\n\
 	movq _rtld_local(%rip), %rdi\n\
 	# env -> rcx\n\
-	leaq 16(%rsp,%rdx,8), %rcx\n\
+	leaq 16(%r13,%rdx,8), %rcx\n\
 	# argv -> rdx\n\
-	leaq 8(%rsp), %rdx\n\
+	leaq 8(%r13), %rdx\n\
+	# Clear %rbp to mark outermost frame obviously even for constructors.\n\
+	xorq %rbp, %rbp\n\
 	# Call the function to run the initializers.\n\
 	call _dl_init_internal@PLT\n\
 	# Pass our finalizer function to the user in %rdx, as per ELF ABI.\n\
 	leaq _dl_fini(%rip), %rdx\n\
+	# And make sure %rsp points to argc stored on the stack.\n\
+	movq %r13, %rsp\n\
 	# Jump to the user's entry point.\n\
 	jmp *%r12\n\
 .previous\n\
@@ -348,9 +235,14 @@ elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc,
   return value;
 }
 
+
+/* Names of the architecture-specific auditing callback functions.  */
+#define ARCH_LA_PLTENTER x86_64_gnu_pltenter
+#define ARCH_LA_PLTEXIT x86_64_gnu_pltexit
+
 #endif /* !dl_machine_h */
 
-#ifdef RESOLVE
+#ifdef RESOLVE_MAP
 
 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
    MAP is the object containing the reloc.  */
@@ -390,18 +282,9 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 #ifndef RTLD_BOOTSTRAP
       const Elf64_Sym *const refsym = sym;
 #endif
-#if defined USE_TLS && !defined RTLD_BOOTSTRAP
       struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
       Elf64_Addr value = (sym == NULL ? 0
 			  : (Elf64_Addr) sym_map->l_addr + sym->st_value);
-#else
-      Elf64_Addr value = RESOLVE (&sym, version, r_type);
-
-# ifndef RTLD_BOOTSTRAP
-      if (sym != NULL)
-# endif
-	value += sym->st_value;
-#endif
 
 #if defined RTLD_BOOTSTRAP && !USE___THREAD
       assert (r_type == R_X86_64_GLOB_DAT || r_type == R_X86_64_JUMP_SLOT);
@@ -553,4 +436,4 @@ elf_machine_lazy_rel (struct link_map *map,
     _dl_reloc_bad_type (map, r_type, 1);
 }
 
-#endif /* RESOLVE */
+#endif /* RESOLVE_MAP */
diff --git a/sysdeps/x86_64/dl-trampoline.S b/sysdeps/x86_64/dl-trampoline.S
new file mode 100644
index 0000000000..eb46f29cf2
--- /dev/null
+++ b/sysdeps/x86_64/dl-trampoline.S
@@ -0,0 +1,188 @@
+/* PLT trampolines.  x86-64 version.
+   Copyright (C) 2004, 2005 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 <sysdep.h>
+
+	.text
+	.globl _dl_runtime_resolve
+	.type _dl_runtime_resolve, @function
+	.align 16
+	cfi_startproc
+_dl_runtime_resolve:
+	subq $56,%rsp
+	cfi_adjust_cfa_offset(72) # Incorporate PLT
+	movq %rax,(%rsp)	# Preserve registers otherwise clobbered.
+	movq %rcx, 8(%rsp)
+	movq %rdx, 16(%rsp)
+	movq %rsi, 24(%rsp)
+	movq %rdi, 32(%rsp)
+	movq %r8, 40(%rsp)
+	movq %r9, 48(%rsp)
+	movq 64(%rsp), %rsi	# Copy args pushed by PLT in register.
+	movq %rsi, %r11		# Multiply by 24
+	addq %r11, %rsi
+	addq %r11, %rsi
+	shlq $3, %rsi
+	movq 56(%rsp), %rdi	# %rdi: link_map, %rsi: reloc_offset
+	call _dl_fixup		# Call resolver.
+	movq %rax, %r11		# Save return value
+	movq 48(%rsp), %r9	# Get register content back.
+	movq 40(%rsp), %r8
+	movq 32(%rsp), %rdi
+	movq 24(%rsp), %rsi
+	movq 16(%rsp), %rdx
+	movq 8(%rsp), %rcx
+	movq (%rsp), %rax
+	addq $72, %rsp		# Adjust stack(PLT did 2 pushes)
+	cfi_adjust_cfa_offset(-72)
+	jmp *%r11		# Jump to function address.
+	cfi_endproc
+	.size _dl_runtime_resolve, .-_dl_runtime_resolve
+
+
+
+	.globl _dl_runtime_profile
+	.type _dl_runtime_profile, @function
+	.align 16
+	cfi_startproc
+_dl_runtime_profile:
+	subq $80, %rsp
+	cfi_adjust_cfa_offset(96) # Incorporate PLT
+	movq %rax, (%rsp)	# Preserve registers otherwise clobbered.
+	movq %rdx, 8(%rsp)
+	movq %r8, 16(%rsp)
+	movq %r9, 24(%rsp)
+	movq %rcx, 32(%rsp)
+	movq %rsi, 40(%rsp)
+	movq %rdi, 48(%rsp)
+	movq %rbp, 56(%rsp)	# Information for auditors.
+	leaq 96(%rsp), %rax
+	movq %rax, 64(%rsp)
+	leaq 8(%rsp), %rcx
+	movq 96(%rsp), %rdx	# Load return address if needed
+	movq 88(%rsp), %rsi	# Copy args pushed by PLT in register.
+	movq %rsi,%r11		# Multiply by 24
+	addq %r11,%rsi
+	addq %r11,%rsi
+	shlq $3, %rsi
+	movq 80(%rsp), %rdi	# %rdi: link_map, %rsi: reloc_offset
+	leaq 72(%rsp), %r8
+	call _dl_profile_fixup	# Call resolver.
+	movq %rax, %r11		# Save return value
+	movq 8(%rsp), %rdx	# Get back register content.
+	movq 16(%rsp), %r8
+	movq 24(%rsp), %r9
+	movq (%rsp),%rax
+	movq 72(%rsp), %r10
+	testq %r10, %r10
+	jns 1f
+	movq 32(%rsp), %rcx
+	movq 40(%rsp), %rsi
+	movq 48(%rsp), %rdi
+	addq $96,%rsp		# Adjust stack
+	cfi_adjust_cfa_offset (-96)
+	jmp *%r11		# Jump to function address.
+
+	/*
+	    +96     return address
+	    +88     PLT2
+	    +80     PLT1
+	    +72     free
+	    +64     %rsp
+	    +56     %rbp
+	    +48     %rdi
+	    +40     %rsi
+	    +32     %rcx
+	    +24     %r9
+	    +16     %r8
+	    +8      %rdx
+	   %esp     %rax
+	*/
+	cfi_adjust_cfa_offset (96)
+1:	movq %rbx, 72(%rsp)
+	cfi_rel_offset (1, 72)
+	leaq 104(%rsp), %rsi
+	movq %rsp, %rbx
+	cfi_def_cfa_register (1)
+	subq %r10, %rsp
+	movq %rsp, %rdi
+	movq %r10, %rcx
+	shrq $3, %rcx
+	rep
+	movsq
+	andq $0xfffffffffffffff0, %rsp
+	movq 32(%rbx), %rcx
+	movq 40(%rbx), %rsi
+	movq 48(%rbx), %rdi
+	call *%r11
+	movq %rbx, %rsp
+	cfi_def_cfa_register (7)
+	subq $72, %rsp
+	cfi_adjust_cfa_offset (72)
+	movq %rsp, %rcx
+	movq %rax, (%rcx)
+	movq %rdx, 8(%rcx)
+	/* Even though the stack is correctly aligned to allow using movaps
+	   we use movups.  Some callers might provide an incorrectly aligned
+	   stack and we do not want to have it blow up here.  */
+	movups %xmm0, 16(%rcx)
+	movups %xmm1, 32(%rcx)
+	fstpt 48(%rcx)
+	fstpt 64(%rcx)
+	/*
+	    +168    return address
+	    +160    PLT2
+	    +152    PLT1
+	    +144    free
+	    +136    %rsp
+	    +128    %rbp
+	    +120    %rdi
+	    +112    %rsi
+	    +104    %rcx
+	    +96     %r9
+	    +88     %r8
+	    +80     %rdx
+	    +64     %st1 result
+	    +48     %st result
+	    +32     %xmm1 result
+	    +16     %xmm0 result
+	    +8      %rdx result
+	   %esp     %rax result
+	*/
+	leaq 80(%rsp), %rdx
+	movq 144(%rsp), %rbx
+	cfi_restore (1)
+	movq 160(%rsp), %rsi	# Copy args pushed by PLT in register.
+	movq %rsi,%r11		# Multiply by 24
+	addq %r11,%rsi
+	addq %r11,%rsi
+	shlq $3, %rsi
+	movq 152(%rsp), %rdi	# %rdi: link_map, %rsi: reloc_offset
+	call _dl_call_pltexit
+	movq (%rsp), %rax
+	movq 8(%rsp), %rdx
+	movups 16(%rsp), %xmm0
+	movups 32(%rsp), %xmm1
+	fldt 64(%rsp)
+	fldt 48(%rsp)
+	addq $168, %rsp
+	cfi_adjust_cfa_offset (-168)
+	retq
+	cfi_endproc
+	.size _dl_runtime_profile, .-_dl_runtime_profile