This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch hjl/pr21913 created. glibc-2.26-37-g5b4dd7f


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, hjl/pr21913 has been created
        at  5b4dd7f1b6694f49d5773ff131986cd619c13c9d (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5b4dd7f1b6694f49d5773ff131986cd619c13c9d

commit 5b4dd7f1b6694f49d5773ff131986cd619c13c9d
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Wed Jul 19 14:32:42 2017 -0700

    i386: Add _startup_sbrk and _startup_fatal [BZ #21913]
    
    On Linux/x86, there are 3 ways to make a system call:
    
    1. call *%gs:SYSINFO_OFFSET.  This requires TLS initialization.
    2. call *_dl_sysinfo.  This requires relocation of _dl_sysinfo.
    3. int $0x80.  This works everywhere.
    
    When an object file is compiled with PIC, #1 is prefered since it is
    faster than #3 and doesn't require relocation of _dl_sysinfo.  For
    dynamic executables, ld.so initializes TLS.  However, for static
    executables, before TLS is initialized by __libc_setup_tls, #3 should
    be used for syscalls.  This patch adds _startup_sbrk and _startup_fatal
    to be used in static executables before __libc_setup_tls is called.  By
    default, they are defined to __sbrk and __libc_fatal, respectively.  On
    x86, a special _startup_sbrk is provided and _startup_fatal is turned
    into ABORT_INSTRUCTION.
    
    	[BZ #21913]
    	* csu/libc-tls.c: Include <startup.h>.
    	(__libc_setup_tls): Call _startup_sbrk instead of __sbrk.  Call
    	_startup_fatal instead of __libc_fatal.
    	* elf/dl-tunables.c: Include <startup.h>.
    	(tunables_strdup): Call _startup_sbrk instead of __sbrk.
    	* sysdeps/generic/startup.h: New file.
    	* sysdeps/unix/sysv/linux/i386/startup.h: Likewise.
    	* sysdeps/unix/sysv/linux/i386/startup_sbrk.c: Likewise.
    	* sysdeps/unix/sysv/linux/i386/Makefile (sysdep_routine): Add
    	startup_sbrk if default to PIC.
    	(static-only-routines): Likewise.

diff --git a/csu/libc-tls.c b/csu/libc-tls.c
index 3c897bf..6f0e698 100644
--- a/csu/libc-tls.c
+++ b/csu/libc-tls.c
@@ -16,11 +16,12 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <unistd.h>
+#include <stdio.h>
+#include <startup.h>
 #include <errno.h>
 #include <ldsodefs.h>
 #include <tls.h>
-#include <unistd.h>
-#include <stdio.h>
 #include <sys/param.h>
 
 
@@ -142,11 +143,11 @@ __libc_setup_tls (void)
      _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign
      and dl_tls_static_align.  */
   tcb_offset = roundup (memsz + GL(dl_tls_static_size), max_align);
-  tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
+  tlsblock = _startup_sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align);
 #elif TLS_DTV_AT_TP
   tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1);
-  tlsblock = __sbrk (tcb_offset + memsz + max_align
-		     + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
+  tlsblock = _startup_sbrk (tcb_offset + memsz + max_align
+			    + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
   tlsblock += TLS_PRE_TCB_SIZE;
 #else
   /* In case a model with a different layout for the TCB and DTV
@@ -193,7 +194,7 @@ __libc_setup_tls (void)
 # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
 #endif
   if (__builtin_expect (lossage != NULL, 0))
-    __libc_fatal (lossage);
+    _startup_fatal (lossage);
 
   /* Update the executable's link map with enough information to make
      the TLS routines happy.  */
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 231fb8c..23c89b2 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -18,9 +18,11 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <unistd.h>
+#include <stdio.h>
+#include <startup.h>
 #include <stdint.h>
 #include <stdbool.h>
-#include <unistd.h>
 #include <stdlib.h>
 #include <sysdep.h>
 #include <fcntl.h>
@@ -42,7 +44,9 @@ tunables_strdup (const char *in)
   size_t i = 0;
 
   while (in[i++] != '\0');
-  char *out = __sbrk (i);
+
+  /* Can't use __sbrk before __libc_setup_tls is called.  */
+  char *out = _startup_sbrk (i);
 
   /* FIXME: In reality if the allocation fails, __sbrk will crash attempting to
      set the thread-local errno since the TCB has not yet been set up.  This
diff --git a/sysdeps/generic/startup.h b/sysdeps/generic/startup.h
new file mode 100644
index 0000000..aa63b31
--- /dev/null
+++ b/sysdeps/generic/startup.h
@@ -0,0 +1,30 @@
+/* Generic definitions of functions used by static libc main startup.
+   Copyright (C) 2017 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+static inline void *
+_startup_sbrk (intptr_t __delta)
+{
+  return __sbrk (__delta);
+}
+
+__attribute__ ((__noreturn__))
+static inline void
+_startup_fatal (const char *__message)
+{
+  __libc_fatal (__message);
+}
diff --git a/sysdeps/unix/sysv/linux/i386/Makefile b/sysdeps/unix/sysv/linux/i386/Makefile
index 4080b8c..cefa151 100644
--- a/sysdeps/unix/sysv/linux/i386/Makefile
+++ b/sysdeps/unix/sysv/linux/i386/Makefile
@@ -31,6 +31,10 @@ sysdep_routines += divdi3
 shared-only-routines += divdi3
 CPPFLAGS-divdi3.c = -Din_divdi3_c
 endif
+ifneq (,$(pic-default))
+sysdep_routines += startup_sbrk
+static-only-routines += startup_sbrk
+endif
 endif
 
 ifeq ($(subdir),nptl)
diff --git a/sysdeps/unix/sysv/linux/i386/startup.h b/sysdeps/unix/sysv/linux/i386/startup.h
new file mode 100644
index 0000000..ccfba45
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/startup.h
@@ -0,0 +1,38 @@
+/* Linux/i386 definitions of functions used by static libc main startup.
+   Copyright (C) 2017 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#if defined PIC && !defined SHARED
+# include <abort-instr.h>
+
+/* Can't use "call *%gs:SYSINFO_OFFSET" during statup in static PIE.  */
+# define I386_USE_SYSENTER 0
+
+extern void * _startup_sbrk (intptr_t) attribute_hidden;
+
+__attribute__ ((__noreturn__))
+static inline void
+_startup_fatal (const char *__message __attribute__ ((unused)))
+{
+  /* This is only called very early during startup in static PIE.
+     FIXME: How can it be improved?  */
+  ABORT_INSTRUCTION;
+  __builtin_unreachable ();
+}
+#else
+# include_next <startup.h>
+#endif
diff --git a/sysdeps/unix/sysv/linux/i386/startup_sbrk.c b/sysdeps/unix/sysv/linux/i386/startup_sbrk.c
new file mode 100644
index 0000000..8239938
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/i386/startup_sbrk.c
@@ -0,0 +1,67 @@
+/* Linux/i386 definitions of _startup_sbrk.
+   Copyright (C) 2017 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, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <startup.h>
+#include <errno.h>
+#include <sysdep.h>
+
+/* Defined in brk.c.  */
+extern void *__curbrk attribute_hidden;
+
+static int
+startup_brk (void *addr)
+{
+  INTERNAL_SYSCALL_DECL (err);
+  void *newbrk = (void *) INTERNAL_SYSCALL_CALL (brk, err, addr);
+  __curbrk = newbrk;
+  if (newbrk < addr)
+    _startup_fatal (NULL);
+  return 0;
+}
+
+/* Extend the process's data space by INCREMENT.  If INCREMENT is negative,
+   shrink data space by - INCREMENT.  Return start of new space allocated,
+   or call _startup_fatal for errors.  */
+
+void *
+_startup_sbrk (intptr_t increment)
+{
+  void *oldbrk;
+
+  /* Update __curbrk from the kernel's brk value.  That way two separate
+     instances of __brk and __sbrk can share the heap, returning
+     interleaved pieces of it.  */
+  if (__curbrk == NULL)
+    if (startup_brk (0) < 0)		/* Initialize the break.  */
+      _startup_fatal (NULL);
+
+  if (increment == 0)
+    return __curbrk;
+
+  oldbrk = __curbrk;
+  if (increment > 0
+      ? ((uintptr_t) oldbrk + (uintptr_t) increment < (uintptr_t) oldbrk)
+      : ((uintptr_t) oldbrk < (uintptr_t) -increment))
+    _startup_fatal (NULL);
+
+  if (startup_brk (oldbrk + increment) < 0)
+    _startup_fatal (NULL);
+
+  return oldbrk;
+}

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


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