diff options
author | Andreas Schwab <aschwab@redhat.com> | 2009-06-10 14:04:22 +0200 |
---|---|---|
committer | Andreas Schwab <aschwab@redhat.com> | 2009-06-10 14:04:22 +0200 |
commit | 0d02cb10e8dd8639b86450cf8e597cf5e2e09894 (patch) | |
tree | 0f2174db43a501b946f0600d1b91ae4117977b04 /sysdeps | |
parent | dfbbe67270efa9c03f9444d50d2f98a7a64622b4 (diff) | |
parent | 88ea382fda5af7717f85bb19837c9c99094f3df4 (diff) |
Merge commit 'origin/master' into fedora/master
Conflicts:
ChangeLog
sysdeps/unix/sysv/linux/i386/sysconf.c
sysdeps/x86_64/cacheinfo.c
version.h
Diffstat (limited to 'sysdeps')
63 files changed, 1244 insertions, 265 deletions
diff --git a/sysdeps/generic/dl-irel.h b/sysdeps/generic/dl-irel.h new file mode 100644 index 0000000000..4d7b481e81 --- /dev/null +++ b/sysdeps/generic/dl-irel.h @@ -0,0 +1,23 @@ +/* Machine-dependent ELF indirect relocation inline functions. + Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_IREL_h +#define _DL_IREL_H + +#endif /* dl-irel.h */ diff --git a/sysdeps/i386/____longjmp_chk.S b/sysdeps/i386/____longjmp_chk.S new file mode 100644 index 0000000000..6cd74968a2 --- /dev/null +++ b/sysdeps/i386/____longjmp_chk.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2001,2004,2005,2006,2009 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. */ + + .section .rodata.str1.1,"aMS",@progbits,1 + .type longjmp_msg,@object +longjmp_msg: + .string "longjmp causes uninitialized stack frame" + .size longjmp_msg, .-longjmp_msg + + +#define __longjmp ____longjmp_chk + +#ifdef PIC +# define CALL_FAIL movl %ebx, %ecx; \ + cfi_register(%ebx,%ecx); \ + LOAD_PIC_REG (bx); \ + leal longjmp_msg@GOTOFF(%ebx), %eax; \ + call __GI___fortify_fail@PLT +#else +# define CALL_FAIL movl $longjmp_msg, %eax; \ + call __fortify_fail +#endif + +#define CHECK_ESP(reg) \ + cmpl reg, %esp; \ + jbe .Lok; \ + CALL_FAIL; \ +.Lok: + +#include "__longjmp.S" diff --git a/sysdeps/i386/__longjmp.S b/sysdeps/i386/__longjmp.S index 559d56b250..8b0732056a 100644 --- a/sysdeps/i386/__longjmp.S +++ b/sysdeps/i386/__longjmp.S @@ -1,5 +1,6 @@ /* longjmp for i386. - Copyright (C) 1995-1998,2000,2002,2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1995-1998,2000,2002,2005,2006,2009 + 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 @@ -27,6 +28,7 @@ #define JBUF PARMS #define VAL JBUF+PTR_SIZE + .text ENTRY (BP_SYM (__longjmp)) ENTER @@ -40,6 +42,9 @@ ENTRY (BP_SYM (__longjmp)) movl (JB_SP*4)(%eax), %ecx PTR_DEMANGLE (%edx) PTR_DEMANGLE (%ecx) +# ifdef CHECK_ESP + CHECK_ESP (%ecx) +# endif cfi_def_cfa(%eax, 0) cfi_register(%eip, %edx) cfi_register(%esp, %ecx) @@ -63,6 +68,11 @@ ENTRY (BP_SYM (__longjmp)) movl JBUF(%esp), %ecx /* User's jmp_buf in %ecx. */ CHECK_BOUNDS_BOTH_WIDE (%ecx, JBUF(%esp), $JB_SIZE) +# ifdef CHECK_ESP + movl (JB_SP*4)(%ecx), %eax + CHECK_ESP (%eax) +# endif + movl VAL(%esp), %eax /* Second argument is return value. */ /* Save the return address now. */ movl (JB_PC*4)(%ecx), %edx diff --git a/sysdeps/i386/dl-irel.h b/sysdeps/i386/dl-irel.h new file mode 100644 index 0000000000..810a35050b --- /dev/null +++ b/sysdeps/i386/dl-irel.h @@ -0,0 +1,45 @@ +/* Machine-dependent ELF indirect relocation inline functions. + i386 version. + Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_IREL_H +#define _DL_IREL_H + +#include <stdio.h> +#include <unistd.h> + +#define ELF_MACHINE_IREL 1 + +static inline void +__attribute ((always_inline)) +elf_irel (const Elf32_Rel *reloc) +{ + Elf32_Addr *const reloc_addr = (void *) reloc->r_offset; + const unsigned long int r_type = ELF32_R_TYPE (reloc->r_info); + + if (__builtin_expect (r_type == R_386_IRELATIVE, 1)) + { + Elf64_Addr value = ((Elf32_Addr (*) (void)) (*reloc_addr)) (); + *reloc_addr = value; + } + else + __libc_fatal ("unexpected reloc type in static binary"); +} + +#endif /* dl-irel.h */ diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h index 0e15878d4e..a093d2b151 100644 --- a/sysdeps/i386/dl-machine.h +++ b/sysdeps/i386/dl-machine.h @@ -346,7 +346,8 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, if (sym != NULL && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, - 0)) + 0) + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)) value = ((Elf32_Addr (*) (void)) value) (); switch (r_type) @@ -471,6 +472,11 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc, memcpy (reloc_addr_arg, (void *) value, MIN (sym->st_size, refsym->st_size)); break; + case R_386_IRELATIVE: + value = map->l_addr + *reloc_addr; + value = ((Elf32_Addr (*) (void)) value) (); + *reloc_addr = value; + break; default: _dl_reloc_bad_type (map, r_type, 0); break; @@ -500,6 +506,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value; if (sym != NULL + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1) && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) value = ((Elf32_Addr (*) (void)) value) (); @@ -609,6 +616,11 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc, MIN (sym->st_size, refsym->st_size)); break; # endif /* !RESOLVE_CONFLICT_FIND_MAP */ + case R_386_IRELATIVE: + value = map->l_addr + reloc->r_addend; + value = ((Elf32_Addr (*) (void)) value) (); + *reloc_addr = value; + break; default: /* We add these checks in the version to relocate ld.so only if we are still debugging. */ @@ -703,6 +715,12 @@ elf_machine_lazy_rel (struct link_map *map, # endif } } + else if (__builtin_expect (r_type == R_386_IRELATIVE, 0)) + { + Elf32_Addr value = map->l_addr + *reloc_addr; + value = ((Elf32_Addr (*) (void)) value) (); + *reloc_addr = value; + } else _dl_reloc_bad_type (map, r_type, 1); } @@ -726,6 +744,12 @@ elf_machine_lazy_rela (struct link_map *map, td->arg = (void*)reloc; td->entry = _dl_tlsdesc_resolve_rela; } + else if (__builtin_expect (r_type == R_386_IRELATIVE, 0)) + { + Elf32_Addr value = map->l_addr + reloc->r_addend; + value = ((Elf32_Addr (*) (void)) value) (); + *reloc_addr = value; + } else _dl_reloc_bad_type (map, r_type, 1); } diff --git a/sysdeps/ia64/configure b/sysdeps/ia64/configure new file mode 100644 index 0000000000..88caca5386 --- /dev/null +++ b/sysdeps/ia64/configure @@ -0,0 +1,54 @@ +# This file is generated from configure.in by Autoconf. DO NOT EDIT! + # Local configure fragment for sysdeps/ia64. + +echo "$as_me:$LINENO: checking if -g produces usable source locations for assembler-with-cpp" >&5 +echo $ECHO_N "checking if -g produces usable source locations for assembler-with-cpp... $ECHO_C" >&6 +if test "${libc_cv_cpp_asm_debuginfo+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat > conftest.S <<EOF +#include "confdefs.h" + +/* comment on + two lines */ + ${libc_cv_dot_text} + ${libc_cv_asm_global_directive} foo +foo: + /* Unfortunately this test only works for a real instruction, + not for any of the machine-independent pseudo-ops. + So we just have to assume everybody has a "nop". */ + nop.b 0;; + /* comment */ + nop.b 0;; + /* comment */ + nop.b 0;; +EOF +if { ac_try='${CC-cc} $CPPFLAGS $ASFLAGS -g -c conftest.S 1>&5' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && { + ac_pattern='conftest\.S' + { ac_try='readelf --debug-dump=line conftest.o | + grep $ac_pattern 1>&5' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } + }; then + libc_cv_cpp_asm_debuginfo=yes +else + libc_cv_cpp_asm_debuginfo=no +fi +rm -f conftest* +fi +echo "$as_me:$LINENO: result: $libc_cv_cpp_asm_debuginfo" >&5 +echo "${ECHO_T}$libc_cv_cpp_asm_debuginfo" >&6 +if test $libc_cv_cpp_asm_debuginfo = yes; then + cat >>confdefs.h <<\_ACEOF +#define HAVE_CPP_ASM_DEBUGINFO 1 +_ACEOF + +fi diff --git a/sysdeps/ia64/configure.in b/sysdeps/ia64/configure.in new file mode 100644 index 0000000000..887b4cb2ed --- /dev/null +++ b/sysdeps/ia64/configure.in @@ -0,0 +1,35 @@ +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. +# Local configure fragment for sysdeps/ia64. + +AC_CACHE_CHECK(if -g produces usable source locations for assembler-with-cpp, + libc_cv_cpp_asm_debuginfo, [dnl +cat > conftest.S <<EOF +#include "confdefs.h" + +/* comment on + two lines */ + ${libc_cv_dot_text} + ${libc_cv_asm_global_directive} foo +foo: + /* Unfortunately this test only works for a real instruction, + not for any of the machine-independent pseudo-ops. + So we just have to assume everybody has a "nop". */ + nop.b 0;; + /* comment */ + nop.b 0;; + /* comment */ + nop.b 0;; +EOF +if AC_TRY_COMMAND([${CC-cc} $CPPFLAGS $ASFLAGS -g -c conftest.S 1>&AS_MESSAGE_LOG_FD]) && { + ac_pattern='conftest\.S' + AC_TRY_COMMAND([readelf --debug-dump=line conftest.o | + grep $ac_pattern 1>&AS_MESSAGE_LOG_FD]) + }; then + libc_cv_cpp_asm_debuginfo=yes +else + libc_cv_cpp_asm_debuginfo=no +fi +rm -f conftest*])AC_SUBST(libc_cv_cpp_asm_debuginfo) +if test $libc_cv_cpp_asm_debuginfo = yes; then + AC_DEFINE(HAVE_CPP_ASM_DEBUGINFO) +fi diff --git a/sysdeps/ia64/memchr.S b/sysdeps/ia64/memchr.S index e9a7ba8230..cd062b2dd5 100644 --- a/sysdeps/ia64/memchr.S +++ b/sysdeps/ia64/memchr.S @@ -96,7 +96,8 @@ ENTRY(__memchr) mov pr.rot = 1 << 16 ;; .l2: (p[0]) mov addr[0] = ret0 -(p[0]) ld8 value[0] = [ret0], 8 +(p[0]) ld8.s value[0] = [ret0], 8 // speculative load +(p[MEMLAT]) chk.s value[MEMLAT], .recovery // check and recovery (p[MEMLAT]) xor aux[0] = value[MEMLAT], chrx8 (p[MEMLAT+1]) czx1.r poschr[0] = aux[1] (p[MEMLAT+2]) cmp.ne p7, p0 = 8, poschr[1] @@ -124,6 +125,20 @@ ENTRY(__memchr) mov ar.lc = saved_lc br.ret.sptk.many b0 +.recovery: + adds ret0 = -((MEMLAT + 1) * 8), ret0;; +(p[MEMLAT+1]) add ret0 = -8, ret0;; +(p[MEMLAT+2]) add ret0 = -8, ret0;; +.l4: + mov addr[MEMLAT+2] = ret0 + ld8 tmp = [ret0];; // load the first unchecked 8byte + xor aux[1] = tmp, chrx8;; + czx1.r poschr[1] = aux[1];; + cmp.ne p7, p0 = 8, poschr[1] +(p7) br.cond.spnt .foundit;; + adds ret0 = 8, ret0 // load the next unchecked 8byte + br.sptk .l4;; + END(__memchr) weak_alias (__memchr, memchr) diff --git a/sysdeps/ieee754/ldbl-128/s_cosl.c b/sysdeps/ieee754/ldbl-128/s_cosl.c index d1258b2cf1..ef61c3afdb 100644 --- a/sysdeps/ieee754/ldbl-128/s_cosl.c +++ b/sysdeps/ieee754/ldbl-128/s_cosl.c @@ -44,6 +44,7 @@ * TRIG(x) returns trig(x) nearly rounded */ +#include <errno.h> #include "math.h" #include "math_private.h" @@ -66,7 +67,14 @@ return __kernel_cosl(x,z); /* cos(Inf or NaN) is NaN */ - else if (ix>=0x7fff000000000000LL) return x-x; + else if (ix>=0x7fff000000000000LL) { + if (ix == 0x7fff000000000000LL) { + GET_LDOUBLE_LSW64(n,x); + if (n == 0) + __set_errno (EDOM); + } + return x-x; + } /* argument reduction needed */ else { diff --git a/sysdeps/ieee754/ldbl-128/s_expm1l.c b/sysdeps/ieee754/ldbl-128/s_expm1l.c index 78bbe65b53..a82489bb24 100644 --- a/sysdeps/ieee754/ldbl-128/s_expm1l.c +++ b/sysdeps/ieee754/ldbl-128/s_expm1l.c @@ -53,6 +53,7 @@ +#include <errno.h> #include "math.h" #include "math_private.h" @@ -121,7 +122,10 @@ __expm1l (long double x) /* Overflow. */ if (x > maxlog) - return (big * big); + { + __set_errno (ERANGE); + return (big * big); + } /* Minimum value. */ if (x < minarg) diff --git a/sysdeps/ieee754/ldbl-128/s_sinl.c b/sysdeps/ieee754/ldbl-128/s_sinl.c index 446a75f126..dc509e72e5 100644 --- a/sysdeps/ieee754/ldbl-128/s_sinl.c +++ b/sysdeps/ieee754/ldbl-128/s_sinl.c @@ -44,6 +44,7 @@ * TRIG(x) returns trig(x) nearly rounded */ +#include <errno.h> #include "math.h" #include "math_private.h" @@ -66,7 +67,14 @@ return __kernel_sinl(x,z,0); /* sin(Inf or NaN) is NaN */ - else if (ix>=0x7fff000000000000LL) return x-x; + else if (ix>=0x7fff000000000000LL) { + if (ix == 0x7fff000000000000LL) { + GET_LDOUBLE_LSW64(n,x); + if (n == 0) + __set_errno (EDOM); + } + return x-x; + } /* argument reduction needed */ else { diff --git a/sysdeps/ieee754/ldbl-128/s_tanl.c b/sysdeps/ieee754/ldbl-128/s_tanl.c index ea9d053d9b..2349da67f1 100644 --- a/sysdeps/ieee754/ldbl-128/s_tanl.c +++ b/sysdeps/ieee754/ldbl-128/s_tanl.c @@ -44,6 +44,7 @@ * TRIG(x) returns trig(x) nearly rounded */ +#include <errno.h> #include "math.h" #include "math_private.h" @@ -65,7 +66,14 @@ if(ix <= 0x3ffe921fb54442d1LL) return __kernel_tanl(x,z,1); /* tanl(Inf or NaN) is NaN */ - else if (ix>=0x7fff000000000000LL) return x-x; /* NaN */ + else if (ix>=0x7fff000000000000LL) { + if (ix == 0x7fff000000000000LL) { + GET_LDOUBLE_LSW64(n,x); + if (n == 0) + __set_errno (EDOM); + } + return x-x; /* NaN */ + } /* argument reduction needed */ else { diff --git a/sysdeps/ieee754/ldbl-128ibm/s_cosl.c b/sysdeps/ieee754/ldbl-128ibm/s_cosl.c index 59a8196706..8470850fc8 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_cosl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_cosl.c @@ -44,6 +44,7 @@ * TRIG(x) returns trig(x) nearly rounded */ +#include <errno.h> #include "math.h" #include "math_private.h" #include <math_ldbl_opt.h> @@ -67,9 +68,11 @@ return __kernel_cosl(x,z); /* cos(Inf or NaN) is NaN */ - else if (ix>=0x7ff0000000000000LL) + else if (ix>=0x7ff0000000000000LL) { + if (ix == 0x7ff0000000000000LL) + __set_errno (EDOM); return x-x; - + } /* argument reduction needed */ else { n = __ieee754_rem_pio2l(x,y); diff --git a/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c b/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c index 735006575f..f631eddf59 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_expm1l.c @@ -51,6 +51,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <errno.h> #include "math.h" #include "math_private.h" #include <math_ldbl_opt.h> @@ -120,7 +121,10 @@ __expm1l (long double x) /* Overflow. */ if (x > maxlog) - return (big * big); + { + __set_errno (ERANGE); + return (big * big); + } /* Minimum value. */ if (x < minarg) diff --git a/sysdeps/ieee754/ldbl-128ibm/s_sinl.c b/sysdeps/ieee754/ldbl-128ibm/s_sinl.c index 8cc592c612..bd72225e18 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_sinl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_sinl.c @@ -44,6 +44,7 @@ * TRIG(x) returns trig(x) nearly rounded */ +#include <errno.h> #include "math.h" #include "math_private.h" #include <math_ldbl_opt.h> @@ -67,8 +68,11 @@ return __kernel_sinl(x,z,0); /* sin(Inf or NaN) is NaN */ - else if (ix>=0x7ff0000000000000LL) return x-x; - + else if (ix>=0x7ff0000000000000LL) { + if (ix == 0x7ff0000000000000LL) + __set_errno (EDOM); + return x-x; + } /* argument reduction needed */ else { n = __ieee754_rem_pio2l(x,y); diff --git a/sysdeps/ieee754/ldbl-128ibm/s_tanl.c b/sysdeps/ieee754/ldbl-128ibm/s_tanl.c index ea5a7f0ffb..913f38f243 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_tanl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_tanl.c @@ -44,6 +44,7 @@ * TRIG(x) returns trig(x) nearly rounded */ +#include <errno.h> #include "math.h" #include "math_private.h" #include <math_ldbl_opt.h> @@ -66,8 +67,11 @@ if(ix <= 0x3fe921fb54442d10LL) return __kernel_tanl(x,z,1); /* tanl(Inf or NaN) is NaN */ - else if (ix>=0x7ff0000000000000LL) return x-x; /* NaN */ - + else if (ix>=0x7ff0000000000000LL) { + if (ix == 0x7ff0000000000000LL) + __set_errno (EDOM); + return x-x; /* NaN */ + } /* argument reduction needed */ else { n = __ieee754_rem_pio2l(x,y); diff --git a/sysdeps/mach/hurd/.cvsignore b/sysdeps/mach/hurd/.cvsignore deleted file mode 100644 index 1f69fd919a..0000000000 --- a/sysdeps/mach/hurd/.cvsignore +++ /dev/null @@ -1,4 +0,0 @@ -*.gz *.Z *.tar *.tgz -=* -TODO COPYING* AUTHORS copyr-* copying.* -glibc-* diff --git a/sysdeps/powerpc/powerpc32/____longjmp_chk.S b/sysdeps/powerpc/powerpc32/____longjmp_chk.S new file mode 100644 index 0000000000..5c1f648661 --- /dev/null +++ b/sysdeps/powerpc/powerpc32/____longjmp_chk.S @@ -0,0 +1,37 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <rtld-global-offsets.h> + + .section .rodata.str1.1,"aMS",@progbits,1 +.LC0: + .string "longjmp causes uninitialized stack frame" + .text + +#define __longjmp ____longjmp_chk + +#define CHECK_SP(reg) \ + cmplw reg, r1; \ + bge+ .Lok; \ + lis r3,.LC0@ha; \ + la r3,.LC0@l(r3); \ + bl HIDDEN_JUMPTARGET (__fortify_fail); \ +.Lok: + +#include <__longjmp-common.S> diff --git a/sysdeps/powerpc/powerpc32/__longjmp-common.S b/sysdeps/powerpc/powerpc32/__longjmp-common.S index 2093b7e337..7b1c017837 100644 --- a/sysdeps/powerpc/powerpc32/__longjmp-common.S +++ b/sysdeps/powerpc/powerpc32/__longjmp-common.S @@ -1,5 +1,5 @@ /* longjmp for PowerPC. - Copyright (C) 1995-1997, 1999-2001, 2003, 2004, 2005, 2006 + Copyright (C) 1995-1997, 1999-2001, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -31,7 +31,7 @@ ENTRY (BP_SYM (__longjmp)) CHECK_BOUNDS_BOTH_WIDE_LIT (r3, r8, r9, JB_SIZE) -#ifdef PTR_DEMANGLE +#if defined PTR_DEMANGLE || defined CHECK_SP lwz r24,(JB_GPR1*4)(r3) #else lwz r1,(JB_GPR1*4)(r3) @@ -45,9 +45,17 @@ ENTRY (BP_SYM (__longjmp)) lwz r19,((JB_GPRS+5)*4)(r3) lwz r20,((JB_GPRS+6)*4)(r3) #ifdef PTR_DEMANGLE +# ifdef CHECK_SP + PTR_DEMANGLE3 (r24, r24, r25) +# else PTR_DEMANGLE3 (r1, r24, r25) +# endif PTR_DEMANGLE2 (r0, r25) #endif +#ifdef CHECK_SP + CHECK_SP (r24) + mr r1,r24 +#endif mtlr r0 lwz r21,((JB_GPRS+7)*4)(r3) lwz r22,((JB_GPRS+8)*4)(r3) diff --git a/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S b/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S index f9f010fcac..f105815b9c 100644 --- a/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S +++ b/sysdeps/powerpc/powerpc32/fpu/__longjmp-common.S @@ -114,7 +114,7 @@ L(aligned_restore_vmx): lvx v31,0,r6 L(no_vmx): #endif -#ifdef PTR_DEMANGLE +#if defined PTR_DEMANGLE || defined CHECK_SP lwz r24,(JB_GPR1*4)(r3) #else lwz r1,(JB_GPR1*4)(r3) @@ -135,9 +135,17 @@ L(no_vmx): lwz r20,((JB_GPRS+6)*4)(r3) lfd fp20,((JB_FPRS+6*2)*4)(r3) #ifdef PTR_DEMANGLE +# ifdef CHECK_SP + PTR_DEMANGLE3 (r24, r24, r25) +# else PTR_DEMANGLE3 (r1, r24, r25) +# endif PTR_DEMANGLE2 (r0, r25) #endif +#ifdef CHECK_SP + CHECK_SP (r24) + mr r1,r24 +#endif mtlr r0 lwz r21,((JB_GPRS+7)*4)(r3) lfd fp21,((JB_FPRS+7*2)*4)(r3) diff --git a/sysdeps/powerpc/powerpc64/____longjmp_chk.S b/sysdeps/powerpc/powerpc64/____longjmp_chk.S new file mode 100644 index 0000000000..56549021aa --- /dev/null +++ b/sysdeps/powerpc/powerpc64/____longjmp_chk.S @@ -0,0 +1,39 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <rtld-global-offsets.h> + + .section .rodata.str1.1,"aMS",@progbits,1 +.LC0: + .string "longjmp causes uninitialized stack frame" + .section .toc,"aw" +.LC1: + .tc .LC0[TC],.LC0 + .text + +#define __longjmp ____longjmp_chk + +#define CHECK_SP(reg) \ + cmpld reg, r1; \ + bge+ .Lok; \ + ld r3,.LC1@toc(2); \ + bl HIDDEN_JUMPTARGET (__fortify_fail); \ +.Lok: + +#include <__longjmp-common.S> diff --git a/sysdeps/powerpc/powerpc64/__longjmp-common.S b/sysdeps/powerpc/powerpc64/__longjmp-common.S index 19b2849c01..1be1f8f3bb 100644 --- a/sysdeps/powerpc/powerpc64/__longjmp-common.S +++ b/sysdeps/powerpc/powerpc64/__longjmp-common.S @@ -107,12 +107,22 @@ L(aligned_restore_vmx): lvx v31,0,r6 L(no_vmx): #endif -#ifdef PTR_DEMANGLE +#if defined PTR_DEMANGLE || defined CHECK_SP ld r22,(JB_GPR1*8)(r3) - PTR_DEMANGLE3 (r1, r22, r25) #else ld r1,(JB_GPR1*8)(r3) #endif +#ifdef PTR_DEMANGLE +# ifdef CHECK_SP + PTR_DEMANGLE3 (r22, r22, r25) +# else + PTR_DEMANGLE3 (r1, r22, r25) +# endif +#endif +#ifdef CHECK_SP + CHECK_SP (r22) + mr r1,r22 +#endif ld r2,(JB_GPR2*8)(r3) ld r0,(JB_LR*8)(r3) ld r14,((JB_GPRS+0)*8)(r3) diff --git a/sysdeps/s390/s390-32/____longjmp_chk.c b/sysdeps/s390/s390-32/____longjmp_chk.c new file mode 100644 index 0000000000..c5eb721e0e --- /dev/null +++ b/sysdeps/s390/s390-32/____longjmp_chk.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + 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 <errno.h> +#include <sysdep.h> +#include <setjmp.h> +#include <bits/setjmp.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +#define __longjmp ____longjmp_chk + +#define CHECK_SP(env, guard) \ + do \ + { \ + uintptr_t cur_sp; \ + uintptr_t new_sp = env->__gregs[9]; \ + __asm ("lr %0, %%r15" : "=r" (cur_sp)); \ + new_sp ^= guard; \ + if (new_sp < cur_sp) \ + __fortify_fail ("longjmp causes uninitialized stack frame"); \ + } while (0) + +#include "__longjmp.c" diff --git a/sysdeps/s390/s390-32/__longjmp.c b/sysdeps/s390/s390-32/__longjmp.c index c47ebbc52a..4abc0ec81c 100644 --- a/sysdeps/s390/s390-32/__longjmp.c +++ b/sysdeps/s390/s390-32/__longjmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000, 2001, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001, 2005, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). @@ -33,6 +33,11 @@ __longjmp (__jmp_buf env, int val) #ifdef PTR_DEMANGLE register uintptr_t r3 __asm ("%r3") = THREAD_GET_POINTER_GUARD (); register void *r1 __asm ("%r1") = (void *) env; +# ifdef CHECK_SP + CHECK_SP (env, r3); +# endif +#elif defined CHECK_SP + CHECK_SP (env, 0); #endif /* Restore registers and jump back. */ asm volatile ("ld %%f6,48(%1)\n\t" diff --git a/sysdeps/s390/s390-64/____longjmp_chk.c b/sysdeps/s390/s390-64/____longjmp_chk.c new file mode 100644 index 0000000000..241822ce4a --- /dev/null +++ b/sysdeps/s390/s390-64/____longjmp_chk.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>. + + 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 <errno.h> +#include <sysdep.h> +#include <setjmp.h> +#include <bits/setjmp.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +#define __longjmp ____longjmp_chk + +#define CHECK_SP(env, guard) \ + do \ + { \ + uintptr_t cur_sp; \ + uintptr_t new_sp = env->__gregs[9]; \ + __asm ("lgr %0, %%r15" : "=r" (cur_sp)); \ + new_sp ^= guard; \ + if (new_sp < cur_sp) \ + __fortify_fail ("longjmp causes uninitialized stack frame"); \ + } while (0) + +#include "__longjmp.c" diff --git a/sysdeps/s390/s390-64/__longjmp.c b/sysdeps/s390/s390-64/__longjmp.c index 030fb5b515..445bd3baf3 100644 --- a/sysdeps/s390/s390-64/__longjmp.c +++ b/sysdeps/s390/s390-64/__longjmp.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2001, 2005, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). @@ -33,6 +33,11 @@ __longjmp (__jmp_buf env, int val) #ifdef PTR_DEMANGLE register uintptr_t r3 __asm ("%r3") = THREAD_GET_POINTER_GUARD (); register void *r1 __asm ("%r1") = (void *) env; +# ifdef CHECK_SP + CHECK_SP (env, r3); +# endif +#elif defined CHECK_SP + CHECK_SP (env, 0); #endif /* Restore registers and jump back. */ asm volatile ("ld %%f7,104(%1)\n\t" diff --git a/sysdeps/sh/____longjmp_chk.S b/sysdeps/sh/____longjmp_chk.S new file mode 100644 index 0000000000..2ff4f586ef --- /dev/null +++ b/sysdeps/sh/____longjmp_chk.S @@ -0,0 +1,70 @@ +/* Copyright (C) 2009 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. */ + + .section .rodata.str1.1,"aMS",@progbits,1 + .type longjmp_msg,@object +longjmp_msg: + .string "longjmp causes uninitialized stack frame" + .size longjmp_msg, .-longjmp_msg + .text + +#define __longjmp ____longjmp_chk + +#ifdef PIC +# define CALL_FAIL \ + mov.l .Lfail, r1; \ + mov.l .Lstr, r4; \ + mova .Lgot, r0; \ + mov.l .Lgot, r12; \ + add r0, r12; \ + bsrf r1; \ + add r12, r4; \ +.Lfail0: \ + bra 0f; \ + nop; \ + .align 2; \ +.Lgot: \ + .long _GLOBAL_OFFSET_TABLE_; \ +.Lstr: \ + .long longjmp_msg@GOTOFF; \ +.Lfail: \ + .long __GI___fortify_fail@PLT-(.Lfail0-.); \ +0: +#else +# define CALL_FAIL \ + mov.l .Lfail, r1; \ + mov.l .Lstr, r4; \ + jsr @r1; \ + nop; \ + bra 0f; \ + nop; \ + .align 2; \ +.Lstr: \ + .long longjmp_msg; \ +.Lfail: \ + .long __fortify_fail; \ +0: +#endif + +#define CHECK_SP(reg) \ + cmp/hs r15, reg; \ + bt .Lok; \ + CALL_FAIL \ +.Lok: + +#include <__longjmp.S> diff --git a/sysdeps/sh/sh3/__longjmp.S b/sysdeps/sh/sh3/__longjmp.S index c6d8a3214c..8c84aff9b4 100644 --- a/sysdeps/sh/sh3/__longjmp.S +++ b/sysdeps/sh/sh3/__longjmp.S @@ -1,5 +1,5 @@ /* longjmp for SH. - Copyright (C) 1999, 2000, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1999, 2000, 2005, 2006, 2009 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 @@ -42,6 +42,9 @@ ENTRY (__longjmp) mov r2, r14 mov.l @r4+, r2 PTR_DEMANGLE2 (r2, r1) +# ifdef CHECK_SP + CHECK_SP (r2) +# endif mov r2, r15 mov.l @r4+, r2 PTR_DEMANGLE2 (r2, r1) @@ -49,6 +52,10 @@ ENTRY (__longjmp) mov #0, r1 #else mov.l @r4+, r14 +# ifdef CHECK_SP + mov.l @r4, r2 + CHECK_SP (r2) +# endif mov.l @r4+, r15 lds.l @r4+, pr #endif diff --git a/sysdeps/sh/sh4/__longjmp.S b/sysdeps/sh/sh4/__longjmp.S index 2fd137bcba..f2e4b7535a 100644 --- a/sysdeps/sh/sh4/__longjmp.S +++ b/sysdeps/sh/sh4/__longjmp.S @@ -42,6 +42,9 @@ ENTRY (__longjmp) mov r2, r14 mov.l @r4+, r2 PTR_DEMANGLE2 (r2, r1) +# ifdef CHECK_SP + CHECK_SP (r2) +# endif mov r2, r15 mov.l @r4+, r2 PTR_DEMANGLE2 (r2, r1) @@ -49,6 +52,10 @@ ENTRY (__longjmp) mov #0, r1 #else mov.l @r4+, r14 +# ifdef CHECK_SP + mov.l @r4, r2 + CHECK_SP (r2) +# endif mov.l @r4+, r15 lds.l @r4+, pr #endif diff --git a/sysdeps/unix/common/.cvsignore b/sysdeps/unix/common/.cvsignore deleted file mode 100644 index 1f69fd919a..0000000000 --- a/sysdeps/unix/common/.cvsignore +++ /dev/null @@ -1,4 +0,0 @@ -*.gz *.Z *.tar *.tgz -=* -TODO COPYING* AUTHORS copyr-* copying.* -glibc-* diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 170c042dd1..cee5d29255 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -11,6 +11,10 @@ ifeq ($(subdir),malloc) CFLAGS-malloc.c += -DMORECORE_CLEARS=2 endif +ifeq ($(subdir),socket) +sysdep_routines += internal_accept4 +endif + ifeq ($(subdir),misc) sysdep_routines += sysctl clone llseek umount umount2 readahead \ setfsuid setfsgid makedev epoll_pwait signalfd \ diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions index b348570bda..2b5f2fb03c 100644 --- a/sysdeps/unix/sysv/linux/Versions +++ b/sysdeps/unix/sysv/linux/Versions @@ -139,7 +139,7 @@ libc { epoll_create1; inotify_init1; } GLIBC_2.10 { - fallocate; fallocate64; + fallocate; } GLIBC_PRIVATE { # functions used in other libraries diff --git a/sysdeps/unix/sysv/linux/accept4.c b/sysdeps/unix/sysv/linux/accept4.c index 97f7b8ce62..9ef9f479b0 100644 --- a/sysdeps/unix/sysv/linux/accept4.c +++ b/sysdeps/unix/sysv/linux/accept4.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2008 Free Software Foundation, Inc. +/* Copyright (C) 2008, 2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2008. @@ -23,8 +23,7 @@ #include <sysdep-cancel.h> #include <sys/syscall.h> - -#define __NR_accept4 288 +#include <kernel-features.h> #ifdef __NR_accept4 @@ -43,6 +42,50 @@ accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags) return result; } +#elif defined __NR_socketcall +# ifndef __ASSUME_ACCEPT4 +extern int __internal_accept4 (int fd, __SOCKADDR_ARG addr, + socklen_t *addr_len, int flags) + attribute_hidden; + +static int have_accept4; + +int +accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags) +{ + if (__builtin_expect (have_accept4 >= 0, 1)) + { + int ret = __internal_accept4 (fd, addr, addr_len, flags); + /* The kernel returns -EINVAL for unknown socket operations. + We need to convert that error to an ENOSYS error. */ + if (__builtin_expect (ret < 0, 0) + && have_accept4 == 0 + && errno == EINVAL) + { + /* Try another call, this time with the FLAGS parameter + cleared and an invalid file descriptor. This call will not + cause any harm and it will return immediately. */ + ret = __internal_accept4 (-1, addr, addr_len, 0); + if (errno == EINVAL) + { + have_accept4 = -1; + __set_errno (ENOSYS); + } + else + { + have_accept4 = 1; + __set_errno (EINVAL); + } + return -1; + } + return ret; + } + __set_errno (ENOSYS); + return -1; +} +# else +/* When __ASSUME_ACCEPT4 accept4 is defined in internal_accept4.S. */ +# endif #else int accept4 (int fd, __SOCKADDR_ARG addr, socklen_t *addr_len, int flags) diff --git a/sysdeps/unix/sysv/linux/fallocate64.c b/sysdeps/unix/sysv/linux/fallocate64.c index ebcaf671b3..751a7b2275 100644 --- a/sysdeps/unix/sysv/linux/fallocate64.c +++ b/sysdeps/unix/sysv/linux/fallocate64.c @@ -23,7 +23,7 @@ /* Reserve storage for the data of the file associated with FD. */ int -__fallocate64_l64 (int fd, int mode, __off64_t offset, __off64_t len) +fallocate64 (int fd, int mode, __off64_t offset, __off64_t len) { #ifdef __NR_fallocate return INLINE_SYSCALL (fallocate, 6, fd, mode, diff --git a/sysdeps/unix/sysv/linux/i386/Versions b/sysdeps/unix/sysv/linux/i386/Versions index abd1d152d7..f3544acb75 100644 --- a/sysdeps/unix/sysv/linux/i386/Versions +++ b/sysdeps/unix/sysv/linux/i386/Versions @@ -41,6 +41,10 @@ libc { # v* vm86; } + GLIBC_2.11 { + # f* + fallocate64; + } GLIBC_PRIVATE { __modify_ldt; } diff --git a/sysdeps/unix/sysv/linux/i386/accept4.S b/sysdeps/unix/sysv/linux/i386/accept4.S index 087ccc456f..1d05eff7f7 100644 --- a/sysdeps/unix/sysv/linux/i386/accept4.S +++ b/sysdeps/unix/sysv/linux/i386/accept4.S @@ -24,10 +24,6 @@ #define EINVAL 22 #define ENOSYS 38 -#ifndef SOCKOP_accept4 -# define SOCKOP_accept4 18 -#endif - #ifdef __ASSUME_ACCEPT4 # define errlabel SYSCALL_ERROR_LABEL #else diff --git a/sysdeps/unix/sysv/linux/i386/fallocate64.c b/sysdeps/unix/sysv/linux/i386/fallocate64.c index b744710a96..4998f5e644 100644 --- a/sysdeps/unix/sysv/linux/i386/fallocate64.c +++ b/sysdeps/unix/sysv/linux/i386/fallocate64.c @@ -26,7 +26,7 @@ extern int __call_fallocate (int fd, int mode, __off64_t offset, __off64_t len) /* Reserve storage for the data of the file associated with FD. */ int -__fallocate64_l64 (int fd, int mode, __off64_t offset, __off64_t len) +fallocate64 (int fd, int mode, __off64_t offset, __off64_t len) { return __call_fallocate (fd, mode, offset, len); } diff --git a/sysdeps/unix/sysv/linux/i386/internal_accept4.S b/sysdeps/unix/sysv/linux/i386/internal_accept4.S new file mode 100644 index 0000000000..c3f1630494 --- /dev/null +++ b/sysdeps/unix/sysv/linux/i386/internal_accept4.S @@ -0,0 +1 @@ +/* Not needed, accept4.S has everything. */ diff --git a/sysdeps/unix/sysv/linux/i386/sysconf.c b/sysdeps/unix/sysv/linux/i386/sysconf.c index f59e0c3fad..efe1a639cd 100644 --- a/sysdeps/unix/sysv/linux/i386/sysconf.c +++ b/sysdeps/unix/sysv/linux/i386/sysconf.c @@ -1,5 +1,5 @@ /* Get file-specific information about a file. Linux version. - Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006, 2007, 2009 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 @@ -67,76 +67,77 @@ handle_i486 (int name) static const struct intel_02_cache_info { - unsigned int idx; - int name; - long int size; - long int assoc; - long int linesize; -} intel_02_known[] = + unsigned char idx; + unsigned char assoc; + unsigned char linesize; + unsigned char rel_name; + unsigned int size; +} intel_02_known [] = { - { 0x06, _SC_LEVEL1_ICACHE_SIZE, 8192, 4, 32 }, - { 0x08, _SC_LEVEL1_ICACHE_SIZE, 16384, 4, 32 }, - { 0x09, _SC_LEVEL1_ICACHE_SIZE, 32768, 4, 32 }, - { 0x0a, _SC_LEVEL1_DCACHE_SIZE, 8192, 2, 32 }, - { 0x0c, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 32 }, - { 0x0d, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 }, - { 0x21, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 }, - { 0x22, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 }, - { 0x23, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 }, - { 0x25, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 }, - { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 }, - { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 }, - { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 }, - { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 }, - { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 }, - { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 }, - { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 }, - { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 }, - { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, - { 0x3f, _SC_LEVEL2_CACHE_SIZE, 262144, 2, 64 }, - { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 }, - { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 }, - { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 }, - { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 }, - { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 }, - { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 }, - { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 }, - { 0x48, _SC_LEVEL2_CACHE_SIZE, 3145728, 12, 64 }, - { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 }, - { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 }, - { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 }, - { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 }, - { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 }, - { 0x4e, _SC_LEVEL2_CACHE_SIZE, 6291456, 24, 64 }, - { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 }, - { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 }, - { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 }, - { 0x68, _SC_LEVEL1_DCACHE_SIZE, 32768, 4, 64 }, - { 0x78, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0x79, _SC_LEVEL2_CACHE_SIZE, 131072, 8, 64 }, - { 0x7a, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 }, - { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 }, - { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 }, - { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 }, - { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 }, - { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 }, - { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 }, - { 0x85, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 32 }, - { 0x86, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, - { 0x87, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0xd0, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 }, - { 0xd1, _SC_LEVEL3_CACHE_SIZE, 1048576, 4, 64 }, - { 0xd2, _SC_LEVEL3_CACHE_SIZE, 2097152, 4, 64 }, - { 0xd6, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 }, - { 0xd7, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 }, - { 0xd8, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 }, - { 0xdc, _SC_LEVEL3_CACHE_SIZE, 2097152, 12, 64 }, - { 0xdd, _SC_LEVEL3_CACHE_SIZE, 4194304, 12, 64 }, - { 0xde, _SC_LEVEL3_CACHE_SIZE, 8388608, 12, 64 }, - { 0xe3, _SC_LEVEL3_CACHE_SIZE, 2097152, 16, 64 }, - { 0xe3, _SC_LEVEL3_CACHE_SIZE, 4194304, 16, 64 }, - { 0xe4, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 }, +#define M(sc) ((sc) - _SC_LEVEL1_ICACHE_SIZE) + { 0x06, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 8192 }, + { 0x08, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 16384 }, + { 0x09, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, + { 0x0a, 2, 32, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, + { 0x0c, 4, 32, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x0d, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x21, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x22, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, + { 0x23, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, + { 0x25, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0x29, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0x2c, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, + { 0x30, 8, 64, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, + { 0x39, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x3a, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 196608 }, + { 0x3b, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x3c, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x3d, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 393216 }, + { 0x3e, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x3f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x41, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x42, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x43, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x44, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x45, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, + { 0x46, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0x47, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, + { 0x48, 12, 64, M(_SC_LEVEL2_CACHE_SIZE), 3145728 }, + { 0x49, 16, 64, M(_SC_LEVEL2_CACHE_SIZE), 4194304 }, + { 0x4a, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 6291456 }, + { 0x4b, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, + { 0x4c, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 }, + { 0x4d, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 16777216 }, + { 0x4e, 24, 64, M(_SC_LEVEL2_CACHE_SIZE), 6291456 }, + { 0x60, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x66, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, + { 0x67, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x68, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, + { 0x78, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x79, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x7a, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x7b, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x7c, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x7d, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, + { 0x7f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x82, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x83, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x84, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x85, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, + { 0x86, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x87, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0xd0, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, + { 0xd1, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, + { 0xd2, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xd6, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, + { 0xd7, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xd8, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0xdc, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xdd, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0xde, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, + { 0xe3, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xe3, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0xe4, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, }; #define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known[0])) @@ -168,8 +169,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, /* Fold the name. The _SC_ constants are always in the order SIZE, ASSOC, LINESIZE. */ - int folded_name = (_SC_LEVEL1_ICACHE_SIZE - + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3); + int folded_rel_name = (M(name) / 3) * 3; while (value != 0) { @@ -179,13 +179,13 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, { *no_level_2_or_3 = true; - if (folded_name == _SC_LEVEL3_CACHE_SIZE) + if (folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) /* No need to look further. */ break; } else { - if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE) + if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) { /* Intel reused this value. For family 15, model 6 it specifies the 3rd level cache. Otherwise the 2nd @@ -208,7 +208,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, the caller asked for the level 2 cache. */ name = (_SC_LEVEL2_CACHE_SIZE + (name - _SC_LEVEL3_CACHE_SIZE)); - folded_name = _SC_LEVEL3_CACHE_SIZE; + folded_rel_name = M(_SC_LEVEL2_CACHE_SIZE); } } @@ -220,9 +220,9 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, sizeof (intel_02_known[0]), intel_02_known_compare); if (found != NULL) { - if (found->name == folded_name) + if (found->rel_name == folded_rel_name) { - unsigned int offset = name - folded_name; + unsigned int offset = M(name) - folded_rel_name; if (offset == 0) /* Cache size. */ @@ -234,7 +234,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, return found->linesize; } - if (found->name == _SC_LEVEL2_CACHE_SIZE) + if (found->rel_name == M(_SC_LEVEL2_CACHE_SIZE)) *has_level_2 = true; } } diff --git a/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S b/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S new file mode 100644 index 0000000000..e097c2288e --- /dev/null +++ b/sysdeps/unix/sysv/linux/ia64/____longjmp_chk.S @@ -0,0 +1,48 @@ +/* Copyright (C) 2009 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. */ + + .section .rodata.str1.8,"aMS",@progbits,1 + .align 8 +.LC0: + .string "longjmp causes uninitialized stack frame" + + .section .sdata,"aws",@progbits + .align 8 + .type longjmp_msg,@object +longjmp_msg: + data8 .LC0 + .size longjmp_msg, .-longjmp_msg + +#define __longjmp ____longjmp_chk + +#ifdef PIC +# define CALL_FAIL __GI___fortify_fail +#else +# define CALL_FAIL __fortify_fail +#endif + +#define CHECK_RSP(reg) \ + cmp.ltu p0, p8 = reg, r12; \ +(p8) br.cond.dpnt .Lok;; \ + addl r28 = @ltoffx(longjmp_msg#), r1;; \ + ld8.mov r28 = [r28], longjmp_msg#;; \ + ld8 out0 = [r28]; \ + br.call.sptk.many b0 = CALL_FAIL#;; \ +.Lok: + +#include "__longjmp.S" diff --git a/sysdeps/unix/sysv/linux/ia64/__longjmp.S b/sysdeps/unix/sysv/linux/ia64/__longjmp.S index aa18fadf9c..2e74904385 100644 --- a/sysdeps/unix/sysv/linux/ia64/__longjmp.S +++ b/sysdeps/unix/sysv/linux/ia64/__longjmp.S @@ -42,7 +42,11 @@ /* __longjmp(__jmp_buf buf, int val) */ LEAF(__longjmp) +#ifdef CHECK_RSP + alloc r8=ar.pfs,2,1,1,0 +#else alloc r8=ar.pfs,2,1,0,0 +#endif mov r27=ar.rsc add r2=0x98,in0 // r2 <- &jmpbuf.orig_jmp_buf_addr ;; @@ -70,14 +74,18 @@ LEAF(__longjmp) add r3=8,in0 // r3 <- &jmpbuf.r1 shl r9=r25,r17 ;; + ld8.fill.nta r28=[r2],16 // r28 <- jmpbuf.sp or r25=r8,r9 ;; mov r26=ar.rnat mov ar.unat=r25 // setup ar.unat (NaT bits for r1, r4-r7, and r12) ;; - ld8.fill.nta sp=[r2],16 // r12 (sp) +#ifdef CHECK_RSP + CHECK_RSP (r28) +#endif ld8.fill.nta gp=[r3],16 // r1 (gp) dep r11=-1,r23,3,6 // r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) + mov sp=r28 // r12 (sp) ;; ld8.nta r16=[r2],16 // caller's unat ld8.nta r17=[r3],16 // fpsr diff --git a/sysdeps/unix/sysv/linux/internal_accept4.S b/sysdeps/unix/sysv/linux/internal_accept4.S new file mode 100644 index 0000000000..ffc553624c --- /dev/null +++ b/sysdeps/unix/sysv/linux/internal_accept4.S @@ -0,0 +1,14 @@ +#include <kernel-features.h> +#include <sys/syscall.h> +#if !defined __NR_accept4 && defined __NR_socketcall +# define socket accept4 +# ifdef __ASSUME_ACCEPT4 +# define __socket accept4 +# else +# define __socket __internal_accept4 +# endif +# define NARGS 4 +# define NEED_CANCELLATION +# define NO_WEAK_ALIAS +# include <socket.S> +#endif diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h index 473360a13c..4562515790 100644 --- a/sysdeps/unix/sysv/linux/kernel-features.h +++ b/sysdeps/unix/sysv/linux/kernel-features.h @@ -521,7 +521,7 @@ /* Support for the accept4 syscall was added in 2.6.28. */ #if __LINUX_KERNEL_VERSION >= 0x02061c \ && (defined __i386__ || defined __x86_64__ || defined __powerpc__ \ - || defined __ia64__ || defined __sparc__ || defined __s390__) + || defined __sparc__ || defined __s390__) # define __ASSUME_ACCEPT4 1 #endif diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/Versions b/sysdeps/unix/sysv/linux/powerpc/powerpc32/Versions index 181d70150c..6fa0119e95 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/Versions +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/Versions @@ -27,4 +27,7 @@ libc { GLIBC_2.3.4 { setcontext; getcontext; swapcontext; makecontext; } + GLIBC_2.11 { + fallocate64; + } } diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/Versions b/sysdeps/unix/sysv/linux/s390/s390-32/Versions index b6d608d0ae..24e0b1d4cd 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/Versions +++ b/sysdeps/unix/sysv/linux/s390/s390-32/Versions @@ -43,6 +43,9 @@ libc { getutmp; getutmpx; } + GLIBC_2.11 { + fallocate64; + } } libutil { diff --git a/sysdeps/unix/sysv/linux/sh/Versions b/sysdeps/unix/sysv/linux/sh/Versions index 763be60222..bd30f928d7 100644 --- a/sysdeps/unix/sysv/linux/sh/Versions +++ b/sysdeps/unix/sysv/linux/sh/Versions @@ -24,4 +24,7 @@ libc { GLIBC_2.3.3 { posix_fadvise64; posix_fallocate64; } + GLIBC_2.11 { + fallocate64; + } } diff --git a/sysdeps/unix/sysv/linux/socketcall.h b/sysdeps/unix/sysv/linux/socketcall.h index 24ec9ee2ac..adf01b6e10 100644 --- a/sysdeps/unix/sysv/linux/socketcall.h +++ b/sysdeps/unix/sysv/linux/socketcall.h @@ -1,5 +1,5 @@ /* ID for functions called via socketcall system call. - Copyright (C) 1995, 1996, 2008 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 2008, 2009 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 @@ -43,6 +43,6 @@ #define SOCKOP_getsockopt 15 #define SOCKOP_sendmsg 16 #define SOCKOP_recvmsg 17 -#define SOCKOP_paccept 18 +#define SOCKOP_accept4 18 #endif /* sys/socketcall.h */ diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/Versions b/sysdeps/unix/sysv/linux/sparc/sparc32/Versions index c585af3602..c9a5b3e9d5 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/Versions +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/Versions @@ -20,4 +20,7 @@ libc { GLIBC_2.3.3 { posix_fadvise64; posix_fallocate64; } + GLIBC_2.11 { + fallocate64; + } } diff --git a/sysdeps/unix/sysv/linux/wordsize-64/Versions b/sysdeps/unix/sysv/linux/wordsize-64/Versions new file mode 100644 index 0000000000..a3b40ccd17 --- /dev/null +++ b/sysdeps/unix/sysv/linux/wordsize-64/Versions @@ -0,0 +1,5 @@ +libc { + GLIBC_2.10 { + fallocate64; + } +} diff --git a/sysdeps/x86_64/____longjmp_chk.S b/sysdeps/x86_64/____longjmp_chk.S new file mode 100644 index 0000000000..030a0dcaa7 --- /dev/null +++ b/sysdeps/x86_64/____longjmp_chk.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2001,2004,2005,2006,2009 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. */ + + .section .rodata.str1.1,"aMS",@progbits,1 + .type longjmp_msg,@object +longjmp_msg: + .string "longjmp causes uninitialized stack frame" + .size longjmp_msg, .-longjmp_msg + + +#define __longjmp ____longjmp_chk + +#ifdef PIC +# define CALL_FAIL leaq longjmp_msg(%rip), %rdi; \ + call __GI___fortify_fail +#else +# define CALL_FAIL movq $longjmp_msg, %rdi; \ + call __fortify_fail +#endif + +#define CHECK_RSP(reg) \ + cmpq reg, %rsp; \ + jbe .Lok; \ + CALL_FAIL; \ +.Lok: + +#include "__longjmp.S" diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S index a68e7a8a4f..24552ece37 100644 --- a/sysdeps/x86_64/__longjmp.S +++ b/sysdeps/x86_64/__longjmp.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2001,2004,2005,2006 Free Software Foundation, Inc. +/* Copyright (C) 2001,2004,2005,2006,2009 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 @@ /* Jump to the position specified by ENV, causing the setjmp call there to return VAL, or 1 if VAL is 0. void __longjmp (__jmp_buf env, int val). */ + .text ENTRY(__longjmp) /* Restore registers. */ movq (JB_RSP*8)(%rdi),%r8 @@ -33,6 +34,9 @@ ENTRY(__longjmp) PTR_DEMANGLE (%r9) PTR_DEMANGLE (%rdx) #endif +#ifdef CHECK_RSP + CHECK_RSP (%r8) +#endif /* We add unwind information for the target here. */ cfi_def_cfa(%rdi, 0) cfi_register(%rsp,%r8) diff --git a/sysdeps/x86_64/cacheinfo.c b/sysdeps/x86_64/cacheinfo.c index 1ec4ca19c9..362687c181 100644 --- a/sysdeps/x86_64/cacheinfo.c +++ b/sysdeps/x86_64/cacheinfo.c @@ -1,5 +1,5 @@ /* x86_64 cache info. - Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2006, 2007, 2009 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 @@ -29,76 +29,77 @@ static const struct intel_02_cache_info { - unsigned int idx; - int name; - long int size; - long int assoc; - long int linesize; + unsigned char idx; + unsigned char assoc; + unsigned char linesize; + unsigned char rel_name; + unsigned int size; } intel_02_known [] = { - { 0x06, _SC_LEVEL1_ICACHE_SIZE, 8192, 4, 32 }, - { 0x08, _SC_LEVEL1_ICACHE_SIZE, 16384, 4, 32 }, - { 0x09, _SC_LEVEL1_ICACHE_SIZE, 32768, 4, 32 }, - { 0x0a, _SC_LEVEL1_DCACHE_SIZE, 8192, 2, 32 }, - { 0x0c, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 32 }, - { 0x0d, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 }, - { 0x21, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 }, - { 0x22, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 }, - { 0x23, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 }, - { 0x25, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 }, - { 0x29, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 }, - { 0x2c, _SC_LEVEL1_DCACHE_SIZE, 32768, 8, 64 }, - { 0x30, _SC_LEVEL1_ICACHE_SIZE, 32768, 8, 64 }, - { 0x39, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 64 }, - { 0x3a, _SC_LEVEL2_CACHE_SIZE, 196608, 6, 64 }, - { 0x3b, _SC_LEVEL2_CACHE_SIZE, 131072, 2, 64 }, - { 0x3c, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 64 }, - { 0x3d, _SC_LEVEL2_CACHE_SIZE, 393216, 6, 64 }, - { 0x3e, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, - { 0x3f, _SC_LEVEL2_CACHE_SIZE, 262144, 2, 64 }, - { 0x41, _SC_LEVEL2_CACHE_SIZE, 131072, 4, 32 }, - { 0x42, _SC_LEVEL2_CACHE_SIZE, 262144, 4, 32 }, - { 0x43, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 32 }, - { 0x44, _SC_LEVEL2_CACHE_SIZE, 1048576, 4, 32 }, - { 0x45, _SC_LEVEL2_CACHE_SIZE, 2097152, 4, 32 }, - { 0x46, _SC_LEVEL3_CACHE_SIZE, 4194304, 4, 64 }, - { 0x47, _SC_LEVEL3_CACHE_SIZE, 8388608, 8, 64 }, - { 0x48, _SC_LEVEL2_CACHE_SIZE, 3145728, 12, 64 }, - { 0x49, _SC_LEVEL2_CACHE_SIZE, 4194304, 16, 64 }, - { 0x4a, _SC_LEVEL3_CACHE_SIZE, 6291456, 12, 64 }, - { 0x4b, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 }, - { 0x4c, _SC_LEVEL3_CACHE_SIZE, 12582912, 12, 64 }, - { 0x4d, _SC_LEVEL3_CACHE_SIZE, 16777216, 16, 64 }, - { 0x4e, _SC_LEVEL2_CACHE_SIZE, 6291456, 24, 64 }, - { 0x60, _SC_LEVEL1_DCACHE_SIZE, 16384, 8, 64 }, - { 0x66, _SC_LEVEL1_DCACHE_SIZE, 8192, 4, 64 }, - { 0x67, _SC_LEVEL1_DCACHE_SIZE, 16384, 4, 64 }, - { 0x68, _SC_LEVEL1_DCACHE_SIZE, 32768, 4, 64 }, - { 0x78, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0x79, _SC_LEVEL2_CACHE_SIZE, 131072, 8, 64 }, - { 0x7a, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 64 }, - { 0x7b, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 64 }, - { 0x7c, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0x7d, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 64 }, - { 0x7f, _SC_LEVEL2_CACHE_SIZE, 524288, 2, 64 }, - { 0x82, _SC_LEVEL2_CACHE_SIZE, 262144, 8, 32 }, - { 0x83, _SC_LEVEL2_CACHE_SIZE, 524288, 8, 32 }, - { 0x84, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 32 }, - { 0x85, _SC_LEVEL2_CACHE_SIZE, 2097152, 8, 32 }, - { 0x86, _SC_LEVEL2_CACHE_SIZE, 524288, 4, 64 }, - { 0x87, _SC_LEVEL2_CACHE_SIZE, 1048576, 8, 64 }, - { 0xd0, _SC_LEVEL3_CACHE_SIZE, 524288, 4, 64 }, - { 0xd1, _SC_LEVEL3_CACHE_SIZE, 1048576, 4, 64 }, - { 0xd2, _SC_LEVEL3_CACHE_SIZE, 2097152, 4, 64 }, - { 0xd6, _SC_LEVEL3_CACHE_SIZE, 1048576, 8, 64 }, - { 0xd7, _SC_LEVEL3_CACHE_SIZE, 2097152, 8, 64 }, - { 0xd8, _SC_LEVEL3_CACHE_SIZE, 4194304, 8, 64 }, - { 0xdc, _SC_LEVEL3_CACHE_SIZE, 2097152, 12, 64 }, - { 0xdd, _SC_LEVEL3_CACHE_SIZE, 4194304, 12, 64 }, - { 0xde, _SC_LEVEL3_CACHE_SIZE, 8388608, 12, 64 }, - { 0xe3, _SC_LEVEL3_CACHE_SIZE, 2097152, 16, 64 }, - { 0xe3, _SC_LEVEL3_CACHE_SIZE, 4194304, 16, 64 }, - { 0xe4, _SC_LEVEL3_CACHE_SIZE, 8388608, 16, 64 }, +#define M(sc) ((sc) - _SC_LEVEL1_ICACHE_SIZE) + { 0x06, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 8192 }, + { 0x08, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 16384 }, + { 0x09, 4, 32, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, + { 0x0a, 2, 32, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, + { 0x0c, 4, 32, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x0d, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x21, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x22, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, + { 0x23, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, + { 0x25, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0x29, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0x2c, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, + { 0x30, 8, 64, M(_SC_LEVEL1_ICACHE_SIZE), 32768 }, + { 0x39, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x3a, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 196608 }, + { 0x3b, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x3c, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x3d, 6, 64, M(_SC_LEVEL2_CACHE_SIZE), 393216 }, + { 0x3e, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x3f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x41, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x42, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x43, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x44, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x45, 4, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, + { 0x46, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0x47, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, + { 0x48, 12, 64, M(_SC_LEVEL2_CACHE_SIZE), 3145728 }, + { 0x49, 16, 64, M(_SC_LEVEL2_CACHE_SIZE), 4194304 }, + { 0x4a, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 6291456 }, + { 0x4b, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, + { 0x4c, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 12582912 }, + { 0x4d, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 16777216 }, + { 0x4e, 24, 64, M(_SC_LEVEL2_CACHE_SIZE), 6291456 }, + { 0x60, 8, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x66, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 8192 }, + { 0x67, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 16384 }, + { 0x68, 4, 64, M(_SC_LEVEL1_DCACHE_SIZE), 32768 }, + { 0x78, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x79, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 131072 }, + { 0x7a, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x7b, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x7c, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x7d, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, + { 0x7f, 2, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x82, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 262144 }, + { 0x83, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x84, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0x85, 8, 32, M(_SC_LEVEL2_CACHE_SIZE), 2097152 }, + { 0x86, 4, 64, M(_SC_LEVEL2_CACHE_SIZE), 524288 }, + { 0x87, 8, 64, M(_SC_LEVEL2_CACHE_SIZE), 1048576 }, + { 0xd0, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 524288 }, + { 0xd1, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, + { 0xd2, 4, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xd6, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 1048576 }, + { 0xd7, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xd8, 8, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0xdc, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xdd, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0xde, 12, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, + { 0xe3, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 2097152 }, + { 0xe3, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 4194304 }, + { 0xe4, 16, 64, M(_SC_LEVEL3_CACHE_SIZE), 8388608 }, }; #define nintel_02_known (sizeof (intel_02_known) / sizeof (intel_02_known [0])) @@ -130,8 +131,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, /* Fold the name. The _SC_ constants are always in the order SIZE, ASSOC, LINESIZE. */ - int folded_name = (_SC_LEVEL1_ICACHE_SIZE - + ((name - _SC_LEVEL1_ICACHE_SIZE) / 3) * 3); + int folded_rel_name = (M(name) / 3) * 3; while (value != 0) { @@ -141,13 +141,13 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, { *no_level_2_or_3 = true; - if (folded_name == _SC_LEVEL3_CACHE_SIZE) + if (folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) /* No need to look further. */ break; } else { - if (byte == 0x49 && folded_name == _SC_LEVEL3_CACHE_SIZE) + if (byte == 0x49 && folded_rel_name == M(_SC_LEVEL3_CACHE_SIZE)) { /* Intel reused this value. For family 15, model 6 it specifies the 3rd level cache. Otherwise the 2nd @@ -170,7 +170,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, the caller asked for the level 2 cache. */ name = (_SC_LEVEL2_CACHE_SIZE + (name - _SC_LEVEL3_CACHE_SIZE)); - folded_name = _SC_LEVEL3_CACHE_SIZE; + folded_rel_name = M(_SC_LEVEL2_CACHE_SIZE); } } @@ -182,9 +182,9 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, sizeof (intel_02_known[0]), intel_02_known_compare); if (found != NULL) { - if (found->name == folded_name) + if (found->rel_name == folded_rel_name) { - unsigned int offset = name - folded_name; + unsigned int offset = M(name) - folded_rel_name; if (offset == 0) /* Cache size. */ @@ -196,7 +196,7 @@ intel_check_word (int name, unsigned int value, bool *has_level_2, return found->linesize; } - if (found->name == _SC_LEVEL2_CACHE_SIZE) + if (found->rel_name == M(_SC_LEVEL2_CACHE_SIZE)) *has_level_2 = true; } } @@ -489,10 +489,10 @@ init_cacheinfo (void) } #ifdef USE_MULTIARCH - eax = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].eax; - ebx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].ebx; - ecx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx; - edx = __cpu_features.cpuid[INTEL_CPUID_INDEX_1].edx; + eax = __cpu_features.cpuid[COMMON_CPUID_INDEX_1].eax; + ebx = __cpu_features.cpuid[COMMON_CPUID_INDEX_1].ebx; + ecx = __cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx; + edx = __cpu_features.cpuid[COMMON_CPUID_INDEX_1].edx; #else asm volatile ("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) diff --git a/sysdeps/x86_64/dl-irel.h b/sysdeps/x86_64/dl-irel.h new file mode 100644 index 0000000000..d2d5c0670e --- /dev/null +++ b/sysdeps/x86_64/dl-irel.h @@ -0,0 +1,45 @@ +/* Machine-dependent ELF indirect relocation inline functions. + x86-64 version. + Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DL_IREL_H +#define _DL_IREL_H + +#include <stdio.h> +#include <unistd.h> + +#define ELF_MACHINE_IRELA 1 + +static inline void +__attribute ((always_inline)) +elf_irela (const Elf64_Rela *reloc) +{ + Elf64_Addr *const reloc_addr = (void *) reloc->r_offset; + const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info); + + if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 1)) + { + Elf64_Addr value = ((Elf64_Addr (*) (void)) reloc->r_addend) (); + *reloc_addr = value; + } + else + __libc_fatal ("unexpected reloc type in static binary"); +} + +#endif /* dl-irel.h */ diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index 4444ae0a71..61a0556d5e 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -298,7 +298,8 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, if (sym != NULL && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, - 0)) + 0) + && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)) value = ((Elf64_Addr (*) (void)) value) (); # if defined RTLD_BOOTSTRAP && !USE___THREAD @@ -442,6 +443,11 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, } break; # endif + case R_X86_64_IRELATIVE: + value = map->l_addr + reloc->r_addend; + value = ((Elf64_Addr (*) (void)) value) (); + *reloc_addr = value; + break; default: _dl_reloc_bad_type (map, r_type, 0); break; @@ -488,6 +494,12 @@ elf_machine_lazy_rel (struct link_map *map, td->entry = (void*)(D_PTR (map, l_info[ADDRIDX (DT_TLSDESC_PLT)]) + map->l_addr); } + else if (__builtin_expect (r_type == R_X86_64_IRELATIVE, 0)) + { + Elf64_Addr value = map->l_addr + reloc->r_addend; + value = ((Elf64_Addr (*) (void)) value) (); + *reloc_addr = value; + } else _dl_reloc_bad_type (map, r_type, 1); } diff --git a/sysdeps/x86_64/multiarch/Makefile b/sysdeps/x86_64/multiarch/Makefile index 2a1e910e06..33d98c36e6 100644 --- a/sysdeps/x86_64/multiarch/Makefile +++ b/sysdeps/x86_64/multiarch/Makefile @@ -1,3 +1,4 @@ ifeq ($(subdir),csu) aux += init-arch +gen-as-const-headers += ifunc-defines.sym endif diff --git a/sysdeps/x86_64/multiarch/ifunc-defines.sym b/sysdeps/x86_64/multiarch/ifunc-defines.sym new file mode 100644 index 0000000000..48d1287246 --- /dev/null +++ b/sysdeps/x86_64/multiarch/ifunc-defines.sym @@ -0,0 +1,15 @@ +#include "init-arch.h" +#include <stddef.h> + +-- + +CPU_FEATURES_SIZE sizeof (struct cpu_features) +KIND_OFFSET offsetof (struct cpu_features, kind) +CPUID_OFFSET offsetof (struct cpu_features, cpuid) +CPUID_SIZE sizeof (struct cpuid_registers) +CPUID_EAX_OFFSET offsetof (struct cpuid_registers, eax) +CPUID_EBX_OFFSET offsetof (struct cpuid_registers, ebx) +CPUID_ECX_OFFSET offsetof (struct cpuid_registers, ecx) +CPUID_EDX_OFFSET offsetof (struct cpuid_registers, edx) + +COMMON_CPUID_INDEX_1 diff --git a/sysdeps/x86_64/multiarch/init-arch.c b/sysdeps/x86_64/multiarch/init-arch.c index eb4365fe32..ec0eb29faf 100644 --- a/sysdeps/x86_64/multiarch/init-arch.c +++ b/sysdeps/x86_64/multiarch/init-arch.c @@ -1,6 +1,6 @@ /* Initialize CPU feature data. This file is part of the GNU C Library. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. Contributed by Ulrich Drepper <drepper@redhat.com>. The GNU C Library is free software; you can redistribute it and/or @@ -41,11 +41,12 @@ __init_cpu_features (void) { __cpu_features.kind = arch_kind_intel; + get_common_cpuid: asm volatile ("cpuid" - : "=a" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].eax), - "=b" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ebx), - "=c" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx), - "=d" (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].edx) + : "=a" (__cpu_features.cpuid[COMMON_CPUID_INDEX_1].eax), + "=b" (__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ebx), + "=c" (__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx), + "=d" (__cpu_features.cpuid[COMMON_CPUID_INDEX_1].edx) : "0" (1)); } /* This spells out "AuthenticAMD". */ @@ -53,12 +54,7 @@ __init_cpu_features (void) { __cpu_features.kind = arch_kind_amd; - asm volatile ("cpuid" - : "=a" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].eax), - "=b" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ebx), - "=c" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ecx), - "=d" (__cpu_features.cpuid[AMD_CPUID_INDEX_1].edx) - : "0" (1)); + goto get_common_cpuid; } else __cpu_features.kind = arch_kind_other; diff --git a/sysdeps/x86_64/multiarch/init-arch.h b/sysdeps/x86_64/multiarch/init-arch.h index 86cd83dc4c..f160ba2a94 100644 --- a/sysdeps/x86_64/multiarch/init-arch.h +++ b/sysdeps/x86_64/multiarch/init-arch.h @@ -1,5 +1,5 @@ /* This file is part of the GNU C Library. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -20,16 +20,9 @@ enum { - INTEL_CPUID_INDEX_1 = 0, + COMMON_CPUID_INDEX_1 = 0, /* Keep the following line at the end. */ - INTEL_CPUID_INDEX_MAX - }; - -enum - { - AMD_CPUID_INDEX_1 = 0, - /* Keep the following line at the end. */ - AMD_CPUID_INDEX_MAX + COMMON_CPUID_INDEX_MAX }; extern struct cpu_features @@ -42,13 +35,13 @@ extern struct cpu_features arch_kind_other } kind; int max_cpuid; - struct + struct cpuid_registers { unsigned int eax; unsigned int ebx; unsigned int ecx; unsigned int edx; - } cpuid[MAX (INTEL_CPUID_INDEX_MAX, AMD_CPUID_INDEX_MAX)]; + } cpuid[COMMON_CPUID_INDEX_MAX]; } __cpu_features attribute_hidden; @@ -61,10 +54,5 @@ extern void __init_cpu_features (void) attribute_hidden; /* Following are the feature tests used throughout libc. */ -#define INTEL_HAS_POPCOUNT \ - (__cpu_features.kind == arch_kind_intel \ - && (__cpu_features.cpuid[INTEL_CPUID_INDEX_1].ecx & (1 << 23)) != 0) - -#define AMD_HAS_POPCOUNT \ - (__cpu_features.kind == arch_kind_amd \ - && (__cpu_features.cpuid[AMD_CPUID_INDEX_1].ecx & (1 << 23)) != 0) +#define HAS_POPCOUNT \ + ((__cpu_features.cpuid[COMMON_CPUID_INDEX_1].ecx & (1 << 23)) != 0) diff --git a/sysdeps/x86_64/multiarch/rawmemchr.S b/sysdeps/x86_64/multiarch/rawmemchr.S new file mode 100644 index 0000000000..93ca631633 --- /dev/null +++ b/sysdeps/x86_64/multiarch/rawmemchr.S @@ -0,0 +1,93 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@redhat.com>. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <ifunc-defines.h> + + +/* Define multiple versions only for the definition in lib. */ +#ifndef NOT_IN_libc + .text +ENTRY(rawmemchr) + .type rawmemchr, @gnu_indirect_function + cmpl $0, __cpu_features+KIND_OFFSET(%rip) + jne 1f + call __init_cpu_features +1: leaq __rawmemchr_sse2(%rip), %rax + testl $(1<<20), __cpu_features+CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET(%rip) + jz 2f + leaq __rawmemchr_sse42(%rip), %rax +2: ret +END(rawmemchr) +strong_alias (rawmemchr, __rawmemchr) + + + .align 16 + .type __rawmemchr_sse42, @function +__rawmemchr_sse42: + cfi_startproc + CALL_MCOUNT + movd %esi, %xmm1 + movq %rdi, %rcx + punpcklbw %xmm1, %xmm1 + andq $~15, %rdi + punpcklbw %xmm1, %xmm1 + orl $0xffffffff, %esi + movdqa (%rdi), %xmm0 + pshufd $0, %xmm1, %xmm1 + subq %rdi, %rcx + pcmpeqb %xmm1, %xmm0 + shl %cl, %esi + pmovmskb %xmm0, %ecx + movl $16, %eax + movl $16, %edx + andl %esi, %ecx + jnz 1f + +2: pcmpestri $0x08, 16(%rdi), %xmm1 + leaq 16(%rdi), %rdi + jnc 2b + + leaq (%rdi,%rcx), %rax + ret + +1: bsfl %ecx, %eax + addq %rdi, %rax + ret + cfi_endproc + .size __rawmemchr_sse42, .-__rawmemchr_sse42 + + +# undef ENTRY +# define ENTRY(name) \ + .type __rawmemchr_sse2, @function; \ + __rawmemchr_sse2: cfi_startproc; \ + CALL_MCOUNT +# undef END +# define END(name) \ + cfi_endproc; .size __rawmemchr_sse2, .-__rawmemchr_sse2 +# undef libc_hidden_builtin_def +/* It doesn't make sense to send libc-internal rawmemchr calls through a PLT. + The speedup we get from using SSE4.2 instruction is likely eaten away + by the indirect call in the PLT. */ +# define libc_hidden_builtin_def(name) \ + .globl __GI___rawmemchr; __GI___rawmemchr = __rawmemchr_sse2 +#endif + +#include "../rawmemchr.S" diff --git a/sysdeps/x86_64/multiarch/sched_cpucount.c b/sysdeps/x86_64/multiarch/sched_cpucount.c index dc20182df4..b6f425e948 100644 --- a/sysdeps/x86_64/multiarch/sched_cpucount.c +++ b/sysdeps/x86_64/multiarch/sched_cpucount.c @@ -1,6 +1,6 @@ /* Count bits in CPU set. x86-64 multi-arch version. This file is part of the GNU C Library. - Copyright (C) 2008 Free Software Foundation, Inc. + Copyright (C) 2008, 2009 Free Software Foundation, Inc. Contributed by Ulrich Drepper <drepper@redhat.com>. The GNU C Library is free software; you can redistribute it and/or @@ -18,25 +18,20 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifdef SHARED -# include <sched.h> -# include "init-arch.h" +#include <sched.h> +#include "init-arch.h" -# define __sched_cpucount static generic_cpucount -# include <posix/sched_cpucount.c> -# undef __sched_cpucount +#define __sched_cpucount static generic_cpucount +#include <posix/sched_cpucount.c> +#undef __sched_cpucount -# define POPCNT(l) \ +#define POPCNT(l) \ ({ __cpu_mask r; \ asm ("popcntq %1, %0" : "=r" (r) : "0" (l));\ r; }) -# define __sched_cpucount static popcount_cpucount -# include <posix/sched_cpucount.c> -# undef __sched_cpucount +#define __sched_cpucount static popcount_cpucount +#include <posix/sched_cpucount.c> +#undef __sched_cpucount libc_ifunc (__sched_cpucount, - INTEL_HAS_POPCOUNT || AMD_HAS_POPCOUNT - ? popcount_cpucount : generic_cpucount); -#else -# include_next <sched_cpucount.c> -#endif + HAS_POPCOUNT ? popcount_cpucount : generic_cpucount); diff --git a/sysdeps/x86_64/multiarch/strlen.S b/sysdeps/x86_64/multiarch/strlen.S new file mode 100644 index 0000000000..79e6a977ec --- /dev/null +++ b/sysdeps/x86_64/multiarch/strlen.S @@ -0,0 +1,93 @@ +/* strlen(str) -- determine the length of the string STR. + Copyright (C) 2009 Free Software Foundation, Inc. + Contributed by Ulrich Drepper <drepper@redhat.com>. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <ifunc-defines.h> + + +/* Define multiple versions only for the definition in libc and for + the DSO. In static binaries we need strlen before the initialization + happened. */ +#if defined SHARED && !defined NOT_IN_libc + .text +ENTRY(strlen) + .type strlen, @gnu_indirect_function + cmpl $0, __cpu_features+KIND_OFFSET(%rip) + jne 1f + call __init_cpu_features +1: leaq __strlen_sse2(%rip), %rax + testl $(1<<20), __cpu_features+CPUID_OFFSET+COMMON_CPUID_INDEX_1*CPUID_SIZE+CPUID_ECX_OFFSET(%rip) + jz 2f + leaq __strlen_sse42(%rip), %rax +2: ret +END(strlen) + + + .align 16 + .type __strlen_sse42, @function +__strlen_sse42: + cfi_startproc + CALL_MCOUNT + pxor %xmm2, %xmm2 + movq %rdi, %rcx + movq %rdi, %r8 + andq $~15, %rdi + movdqa %xmm2, %xmm1 + pcmpeqb (%rdi), %xmm2 + orl $0xffffffff, %esi + subq %rdi, %rcx + shll %cl, %esi + pmovmskb %xmm2, %edx + andl %esi, %edx + jnz 1f + +2: pcmpistri $0x08, 16(%rdi), %xmm1 + leaq 16(%rdi), %rdi + jnz 2b + + leaq (%rdi,%rcx), %rax + subq %r8, %rax + ret + +1: subq %r8, %rdi + bsfl %edx, %eax + addq %rdi, %rax + ret + cfi_endproc + .size __strlen_sse42, .-__strlen_sse42 + + +# undef ENTRY +# define ENTRY(name) \ + .type __strlen_sse2, @function; \ + __strlen_sse2: cfi_startproc; \ + CALL_MCOUNT +# undef END +# define END(name) \ + cfi_endproc; .size __strlen_sse2, .-__strlen_sse2 +# undef libc_hidden_builtin_def +/* It doesn't make sense to send libc-internal strlen calls through a PLT. + The speedup we get from using SSE4.2 instruction is likely eaten away + by the indirect call in the PLT. */ +# define libc_hidden_builtin_def(name) \ + .globl __GI_strlen; __GI_strlen = __strlen_sse2 +#endif + +#include "../strlen.S" diff --git a/sysdeps/x86_64/rawmemchr.S b/sysdeps/x86_64/rawmemchr.S index c3bd771635..cfb4cebf68 100644 --- a/sysdeps/x86_64/rawmemchr.S +++ b/sysdeps/x86_64/rawmemchr.S @@ -34,19 +34,18 @@ ENTRY (rawmemchr) pcmpeqb %xmm1, %xmm0 shl %cl, %esi pmovmskb %xmm0, %ecx - leaq 16(%rdi), %rdi andl %esi, %ecx jnz 1f -2: movdqa (%rdi), %xmm0 +2: movdqa 16(%rdi), %xmm0 leaq 16(%rdi), %rdi pcmpeqb %xmm1, %xmm0 pmovmskb %xmm0, %ecx testl %ecx, %ecx jz 2b -1: bsfl %ecx, %ecx - leaq -16(%rcx,%rdi), %rax +1: bsfl %ecx, %eax + addq %rdi, %rax ret END (rawmemchr) diff --git a/sysdeps/x86_64/strlen.S b/sysdeps/x86_64/strlen.S index 86bb8a50a9..93aee6bef1 100644 --- a/sysdeps/x86_64/strlen.S +++ b/sysdeps/x86_64/strlen.S @@ -23,30 +23,27 @@ .text ENTRY(strlen) + pxor %xmm2, %xmm2 movq %rdi, %rcx movq %rdi, %r8 andq $~15, %rdi - pxor %xmm1, %xmm1 + movdqa %xmm2, %xmm1 + pcmpeqb (%rdi), %xmm2 orl $0xffffffff, %esi - movdqa (%rdi), %xmm0 subq %rdi, %rcx - leaq 16(%rdi), %rdi - pcmpeqb %xmm1, %xmm0 - shl %cl, %esi - pmovmskb %xmm0, %edx - xorl %eax, %eax - negq %r8 + shll %cl, %esi + pmovmskb %xmm2, %edx andl %esi, %edx jnz 1f -2: movdqa (%rdi), %xmm0 +2: movdqa 16(%rdi), %xmm0 leaq 16(%rdi), %rdi pcmpeqb %xmm1, %xmm0 pmovmskb %xmm0, %edx testl %edx, %edx jz 2b -1: leaq -16(%rdi,%r8), %rdi +1: subq %r8, %rdi bsfl %edx, %eax addq %rdi, %rax ret |