From d585b66fa4d11059948f466c9080a6826932358d Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 8 Feb 2005 10:05:09 +0000 Subject: Updated to fedora-glibc-20050208T0948 --- sysdeps/alpha/bits/link.h | 69 +++ sysdeps/alpha/dl-machine.h | 168 +------ sysdeps/alpha/dl-trampoline.S | 361 ++++++++++++++ sysdeps/alpha/fpu/bits/mathinline.h | 17 +- sysdeps/alpha/libc-tls.c | 2 +- sysdeps/arm/bits/link.h | 4 - sysdeps/arm/bits/linkmap.h | 4 + sysdeps/generic/bits/link.h | 5 +- sysdeps/generic/bits/linkmap.h | 4 + sysdeps/generic/dl-fptr.h | 2 + sysdeps/generic/dl-lookupcfg.h | 25 +- sysdeps/generic/dl-tls.c | 411 ++++++++++------ sysdeps/generic/dl-trampoline.c | 1 + sysdeps/generic/ldsodefs.h | 198 ++++++-- sysdeps/generic/libc-start.c | 24 +- sysdeps/generic/libc-tls.c | 11 +- sysdeps/generic/syslog.c | 429 ++++++++++++++++ sysdeps/generic/unsecvars.h | 17 +- sysdeps/generic/wordexp.c | 60 +-- sysdeps/hppa/bits/link.h | 6 - sysdeps/hppa/bits/linkmap.h | 6 + sysdeps/hppa/dl-lookupcfg.h | 6 +- sysdeps/i386/Makefile | 4 + sysdeps/i386/bits/link.h | 65 ++- sysdeps/i386/bits/linkmap.h | 5 + sysdeps/i386/dl-machine.h | 149 ++---- sysdeps/i386/dl-trampoline.S | 182 +++++++ sysdeps/ia64/bits/link.h | 68 ++- sysdeps/ia64/bits/linkmap.h | 5 + sysdeps/ia64/dl-lookupcfg.h | 19 +- sysdeps/ia64/dl-machine.h | 159 +----- sysdeps/ia64/dl-trampoline.S | 537 +++++++++++++++++++++ sysdeps/ia64/fpu/e_logl.c | 1 - sysdeps/ia64/libc-tls.c | 2 +- sysdeps/linkmap.h | 4 + sysdeps/m68k/bits/link.h | 58 +++ sysdeps/m68k/dl-machine.h | 49 +- sysdeps/m68k/dl-trampoline.S | 129 +++++ sysdeps/mach/hurd/tls.h | 9 +- sysdeps/powerpc/powerpc32/bits/link.h | 62 +++ sysdeps/powerpc/powerpc32/dl-machine.c | 5 +- sysdeps/powerpc/powerpc32/dl-machine.h | 175 +------ sysdeps/powerpc/powerpc32/dl-trampoline.S | 174 +++++++ sysdeps/powerpc/powerpc64/bits/link.h | 109 +++++ sysdeps/powerpc/powerpc64/dl-lookupcfg.h | 22 - sysdeps/powerpc/powerpc64/dl-machine.h | 96 +--- sysdeps/powerpc/powerpc64/dl-trampoline.S | 196 ++++++++ sysdeps/powerpc/tst-stack-align.h | 47 ++ sysdeps/s390/bits/link.h | 120 ++++- sysdeps/s390/bits/linkmap.h | 13 + sysdeps/s390/bits/string.h | 14 +- sysdeps/s390/s390-32/dl-machine.h | 151 +----- sysdeps/s390/s390-32/dl-trampoline.S | 133 +++++ sysdeps/s390/s390-64/dl-machine.h | 137 +----- sysdeps/s390/s390-64/dl-trampoline.S | 126 +++++ sysdeps/sh/bits/link.h | 75 ++- sysdeps/sh/bits/linkmap.h | 5 + sysdeps/sh/dl-machine.h | 297 +----------- sysdeps/sh/dl-trampoline.S | 431 +++++++++++++++++ sysdeps/sh/sh4/Versions | 5 + sysdeps/sh/sh4/dl-machine.h | 2 - sysdeps/sh/sh4/dl-trampoline.S | 2 + sysdeps/unix/i386/sysdep.S | 12 +- sysdeps/unix/rewinddir.c | 3 +- sysdeps/unix/sysv/linux/alpha/oldglob.c | 3 +- sysdeps/unix/sysv/linux/dl-execstack.c | 26 +- sysdeps/unix/sysv/linux/futimes.c | 66 ++- sysdeps/unix/sysv/linux/i386/sysdep.h | 37 +- sysdeps/unix/sysv/linux/init-first.c | 1 - sysdeps/unix/sysv/linux/kernel-features.h | 7 +- .../unix/sysv/linux/powerpc/powerpc64/setcontext.S | 10 +- .../sysv/linux/powerpc/powerpc64/swapcontext.S | 10 +- sysdeps/unix/sysv/linux/syslog.c | 10 + sysdeps/x86_64/bits/link.h | 125 ++++- sysdeps/x86_64/bits/linkmap.h | 14 + sysdeps/x86_64/dl-machine.h | 157 +----- sysdeps/x86_64/dl-trampoline.S | 188 ++++++++ 77 files changed, 4550 insertions(+), 1791 deletions(-) create mode 100644 sysdeps/alpha/bits/link.h create mode 100644 sysdeps/alpha/dl-trampoline.S create mode 100644 sysdeps/arm/bits/linkmap.h create mode 100644 sysdeps/generic/bits/linkmap.h create mode 100644 sysdeps/generic/dl-trampoline.c create mode 100644 sysdeps/generic/syslog.c create mode 100644 sysdeps/hppa/bits/linkmap.h create mode 100644 sysdeps/i386/bits/linkmap.h create mode 100644 sysdeps/i386/dl-trampoline.S create mode 100644 sysdeps/ia64/bits/linkmap.h create mode 100644 sysdeps/ia64/dl-trampoline.S delete mode 100644 sysdeps/ia64/fpu/e_logl.c create mode 100644 sysdeps/linkmap.h create mode 100644 sysdeps/m68k/bits/link.h create mode 100644 sysdeps/m68k/dl-trampoline.S create mode 100644 sysdeps/powerpc/powerpc32/bits/link.h create mode 100644 sysdeps/powerpc/powerpc32/dl-trampoline.S create mode 100644 sysdeps/powerpc/powerpc64/bits/link.h create mode 100644 sysdeps/powerpc/powerpc64/dl-trampoline.S create mode 100644 sysdeps/powerpc/tst-stack-align.h create mode 100644 sysdeps/s390/bits/linkmap.h create mode 100644 sysdeps/s390/s390-32/dl-trampoline.S create mode 100644 sysdeps/s390/s390-64/dl-trampoline.S create mode 100644 sysdeps/sh/bits/linkmap.h create mode 100644 sysdeps/sh/dl-trampoline.S create mode 100644 sysdeps/sh/sh4/Versions delete mode 100644 sysdeps/sh/sh4/dl-machine.h create mode 100644 sysdeps/sh/sh4/dl-trampoline.S create mode 100644 sysdeps/unix/sysv/linux/syslog.c create mode 100644 sysdeps/x86_64/bits/linkmap.h create mode 100644 sysdeps/x86_64/dl-trampoline.S (limited to 'sysdeps') 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 directly; use 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 + + .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 /* 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 +#include +#include #include #include #include @@ -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 ). 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 @@ -183,6 +183,22 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), #endif ); +#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]); 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if __STDC__ +#include +#else +#include +#endif + +#include +#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 . @@ -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 directly; use 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 + + .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 directly; use 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 + /* 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 +#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 directly; use 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 + + .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 +# include # include # include @@ -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 directly; use 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 + + .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 directly; use 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 + + .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 +#include + +#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 directly; use 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 @@ -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 + + .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 + + .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 directly; use 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 @@ -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 + + .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 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 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 #include #include +#include #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 #include #include +#include #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, , 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 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 directly; use 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 . @@ -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 + + .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 -- cgit v1.2.3