summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
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