From patchwork Fri Apr 16 09:21:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 42993 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D50833892039; Fri, 16 Apr 2021 09:21:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D50833892039 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1618564864; bh=NbTT9YQRnnQ3CrEftm6oBQKaGLw2KRgtVo7sa4yUHF0=; h=To:Subject:In-Reply-To:References:Date:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=QGTL7ZDsj/CBLGhMR97ocEugQAZxiqcQYaWAYQYaAf6k0EudiLqrz8g/8TsQOJeoI ANUlJiXiG9cgVriQ+tksqmiRY10tjxTLg9arwzSv3kw7sc0NtrgkbuC+KWqO/JnvR7 PX5ziXax1WC27gq0FMqZfu/kA2NCToP/b4nsdo68= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 4173E3892016 for ; Fri, 16 Apr 2021 09:20:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 4173E3892016 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-466-pBEiw2o3N72MLWmNRg2kIA-1; Fri, 16 Apr 2021 05:20:52 -0400 X-MC-Unique: pBEiw2o3N72MLWmNRg2kIA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 45E446D241 for ; Fri, 16 Apr 2021 09:20:51 +0000 (UTC) Received: from oldenburg.str.redhat.com (ovpn-113-139.ams2.redhat.com [10.36.113.139]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8A90910074FC for ; Fri, 16 Apr 2021 09:20:50 +0000 (UTC) To: libc-alpha@sourceware.org Subject: [PATCH v4 10/37] csu: Move calling main out of __libc_start_main_impl In-Reply-To: References: Message-Id: <46037f59c291ff4e2ec80d0f1b92ce1702670742.1618564630.git.fweimer@redhat.com> Date: Fri, 16 Apr 2021 11:21:08 +0200 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Florian Weimer via Libc-alpha From: Florian Weimer Reply-To: Florian Weimer Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" This code depends on whether glibc has unwinding support for a particular port. Reviewed-by: Adhemerval Zanella --- csu/libc-start.c | 74 ++-------------------- sysdeps/generic/libc_start_call_main.h | 24 +++++++ sysdeps/nptl/libc_start_call_main.h | 88 ++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 70 deletions(-) create mode 100644 sysdeps/generic/libc_start_call_main.h create mode 100644 sysdeps/nptl/libc_start_call_main.h diff --git a/csu/libc-start.c b/csu/libc-start.c index 05ff7afddf..8688cba76d 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -58,12 +58,6 @@ uintptr_t __pointer_chk_guard_local # endif #endif -#ifdef HAVE_PTR_NTHREADS -/* We need atomic operations. */ -# include -#endif - - #ifndef SHARED # include # include @@ -123,6 +117,9 @@ apply_irel (void) # define ARCH_INIT_CPU_FEATURES() #endif +/* Obtain the definition of __libc_start_call_main. */ +#include + #ifdef SHARED /* Initialization for dynamic executables. Find the main executable link map and run its init functions. */ @@ -245,9 +242,6 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), void (*fini) (void), void (*rtld_fini) (void), void *stack_end) { - /* Result of the 'main' function. */ - int result; - #ifndef SHARED char **ev = &argv[argc + 1]; @@ -413,68 +407,8 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), #ifndef SHARED _dl_debug_initialize (0, LM_ID_BASE); #endif -#ifdef HAVE_CLEANUP_JMP_BUF - /* Memory for the cancellation buffer. */ - struct pthread_unwind_buf unwind_buf; - - int not_first_call; - DIAG_PUSH_NEEDS_COMMENT; -#if __GNUC_PREREQ (7, 0) - /* This call results in a -Wstringop-overflow warning because struct - pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp - do not use anything beyond the common prefix (they never access - the saved signal mask), so that is a false positive. */ - DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow="); -#endif - not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); - DIAG_POP_NEEDS_COMMENT; - if (__glibc_likely (! not_first_call)) - { - struct pthread *self = THREAD_SELF; - - /* Store old info. */ - unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); - unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); - - /* Store the new cleanup handler info. */ - THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); - - /* Run the program. */ - result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); - } - else - { - /* Remove the thread-local data. */ -# ifdef SHARED - PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); -# else - extern void __nptl_deallocate_tsd (void) __attribute ((weak)); - __nptl_deallocate_tsd (); -# endif - - /* One less thread. Decrement the counter. If it is zero we - terminate the entire process. */ - result = 0; -# ifdef SHARED - unsigned int *ptr = __libc_pthread_functions.ptr_nthreads; -# ifdef PTR_DEMANGLE - PTR_DEMANGLE (ptr); -# endif -# else - extern unsigned int __nptl_nthreads __attribute ((weak)); - unsigned int *const ptr = &__nptl_nthreads; -# endif - - if (! atomic_decrement_and_test (ptr)) - /* Not much left to do but to exit the thread, not the process. */ - __exit_thread (); - } -#else - /* Nothing fancy, just call the function. */ - result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); -#endif - exit (result); + __libc_start_call_main (main, argc, argv MAIN_AUXVEC_PARAM); } /* Starting with glibc 2.34, the init parameter is always NULL. Older diff --git a/sysdeps/generic/libc_start_call_main.h b/sysdeps/generic/libc_start_call_main.h new file mode 100644 index 0000000000..8a06eec4a3 --- /dev/null +++ b/sysdeps/generic/libc_start_call_main.h @@ -0,0 +1,24 @@ +/* Invoking main from __libc_start. Generic version without unwinding. + Copyright (C) 1998-2021 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 + . */ + +_Noreturn static __always_inline void +__libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + int argc, char **argv MAIN_AUXVEC_DECL) +{ + exit (main (argc, argv, __environ MAIN_AUXVEC_PARAM)); +} diff --git a/sysdeps/nptl/libc_start_call_main.h b/sysdeps/nptl/libc_start_call_main.h new file mode 100644 index 0000000000..5218e7ab1e --- /dev/null +++ b/sysdeps/nptl/libc_start_call_main.h @@ -0,0 +1,88 @@ +/* Invoking main from __libc_start_main. nptl version. + Copyright (C) 1998-2021 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 + . */ + +#include + +_Noreturn static void +__libc_start_call_main (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), + int argc, char **argv +#ifdef LIBC_START_MAIN_AUXVEC_ARG + , ElfW(auxv_t) *auxvec +#endif + ) +{ + int result; + + /* Memory for the cancellation buffer. */ + struct pthread_unwind_buf unwind_buf; + + int not_first_call; + DIAG_PUSH_NEEDS_COMMENT; +#if __GNUC_PREREQ (7, 0) + /* This call results in a -Wstringop-overflow warning because struct + pthread_unwind_buf is smaller than jmp_buf. setjmp and longjmp + do not use anything beyond the common prefix (they never access + the saved signal mask), so that is a false positive. */ + DIAG_IGNORE_NEEDS_COMMENT (11, "-Wstringop-overflow="); +#endif + not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + DIAG_POP_NEEDS_COMMENT; + if (__glibc_likely (! not_first_call)) + { + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); + + /* Run the program. */ + result = main (argc, argv, __environ MAIN_AUXVEC_PARAM); + } + else + { + /* Remove the thread-local data. */ +# ifdef SHARED + PTHFCT_CALL (ptr__nptl_deallocate_tsd, ()); +# else + extern void __nptl_deallocate_tsd (void) __attribute ((weak)); + __nptl_deallocate_tsd (); +# endif + + /* One less thread. Decrement the counter. If it is zero we + terminate the entire process. */ + result = 0; +# ifdef SHARED + unsigned int *ptr = __libc_pthread_functions.ptr_nthreads; +# ifdef PTR_DEMANGLE + PTR_DEMANGLE (ptr); +# endif +# else + extern unsigned int __nptl_nthreads __attribute ((weak)); + unsigned int *const ptr = &__nptl_nthreads; +# endif + + if (! atomic_decrement_and_test (ptr)) + /* Not much left to do but to exit the thread, not the process. */ + __exit_thread (); + } + + exit (result); +}