From 17a661ac6f10e9cf51a664ce95ee95c8113c74e8 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 1 Jun 2020 14:11:32 -0700 Subject: [PATCH] x86: Pass argc and argv to __libc_main --- csu/Makefile | 4 ++-- csu/{version.c => libc-version.c} | 8 +++++-- sysdeps/x86/Makefile | 1 + sysdeps/x86/libc-main.S | 38 +++++++++++++++++++++++++++++++ sysdeps/x86/libc-version.c | 30 ++++++++++++++++++++++++ sysdeps/x86_64/start.S | 34 +++++++++++++++++++++------ 6 files changed, 104 insertions(+), 11 deletions(-) rename csu/{version.c => libc-version.c} (93%) create mode 100644 sysdeps/x86/libc-main.S create mode 100644 sysdeps/x86/libc-version.c diff --git a/csu/Makefile b/csu/Makefile index 555ae27dea..951a093f15 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -26,8 +26,8 @@ subdir := csu include ../Makeconfig -routines = init-first libc-start $(libc-init) sysdep version check_fds \ - libc-tls elf-init dso_handle +routines = init-first libc-start $(libc-init) sysdep libc-version \ + check_fds libc-tls elf-init dso_handle aux = errno elide-routines.os = libc-tls static-only-routines = elf-init diff --git a/csu/version.c b/csu/libc-version.c similarity index 93% rename from csu/version.c rename to csu/libc-version.c index 57b49dfd8a..9b0f4cb94b 100644 --- a/csu/version.c +++ b/csu/libc-version.c @@ -61,12 +61,16 @@ __gnu_get_libc_version (void) } weak_alias (__gnu_get_libc_version, gnu_get_libc_version) +#ifndef LIBC_MAIN +# define LIBC_MAIN __libc_main +#endif + /* This function is the entry point for the shared object. Running the library as a program will get here. */ -extern void __libc_main (void) __attribute__ ((noreturn)); +extern void LIBC_MAIN (void) __attribute__ ((noreturn, visibility ("hidden"))); void -__libc_main (void) +LIBC_MAIN (void) { __libc_print_version (); _exit (0); diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile index beab426f67..de6aed89ee 100644 --- a/sysdeps/x86/Makefile +++ b/sysdeps/x86/Makefile @@ -1,5 +1,6 @@ ifeq ($(subdir),csu) gen-as-const-headers += cpu-features-offsets.sym +routines += libc-main endif ifeq ($(subdir),elf) diff --git a/sysdeps/x86/libc-main.S b/sysdeps/x86/libc-main.S new file mode 100644 index 0000000000..2f8dd0be73 --- /dev/null +++ b/sysdeps/x86/libc-main.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2020 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. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + 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 + . */ + + .hidden __x86_libc_main + +#define LIBC_MAIN __x86_libc_main +#include "start.S" diff --git a/sysdeps/x86/libc-version.c b/sysdeps/x86/libc-version.c new file mode 100644 index 0000000000..bac0cda6c7 --- /dev/null +++ b/sysdeps/x86/libc-version.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2020 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 + . */ + +#define LIBC_MAIN __generic_libc_main +#include + +/* This function is the entry point for the shared object. + Running the library as a program will get here. */ + +extern void __x86_libc_main (int, char **) __attribute__ ((noreturn)); + +void +__x86_libc_main (int argc, char **argv) +{ + __generic_libc_main (); +} diff --git a/sysdeps/x86_64/start.S b/sysdeps/x86_64/start.S index 7477b632f7..18d910257b 100644 --- a/sysdeps/x86_64/start.S +++ b/sysdeps/x86_64/start.S @@ -55,7 +55,13 @@ #include -ENTRY (_start) +#ifdef LIBC_MAIN +# define START __libc_main +#else +# define START _start +#endif + +ENTRY (START) /* Clearing frame pointer is insufficient, use CFI. */ cfi_undefined (rip) /* Clear the frame pointer. The ABI suggests this be done, to mark @@ -76,16 +82,24 @@ ENTRY (_start) rtld_fini: %r9 stack_end: stack. */ +#ifdef LIBC_MAIN +# define ARGC_REG rdi +# define ARGV_REG RSI_LP +#else +# define ARGC_REG rsi +# define ARGV_REG RDX_LP +#endif + mov %RDX_LP, %R9_LP /* Address of the shared library termination function. */ #ifdef __ILP32__ mov (%rsp), %esi /* Simulate popping 4-byte argument count. */ add $4, %esp #else - popq %rsi /* Pop the argument count. */ + popq %ARGC_REG /* Pop the argument count. */ #endif /* argv starts just at the current stack top. */ - mov %RSP_LP, %RDX_LP + mov %RSP_LP, %ARGV_REG /* Align the stack to a 16 byte boundary to follow the ABI. */ and $~15, %RSP_LP @@ -96,19 +110,22 @@ ENTRY (_start) which grow downwards). */ pushq %rsp -#ifdef PIC +#ifdef LIBC_MAIN + call LIBC_MAIN +#else +# ifdef PIC /* Pass address of our own entry points to .fini and .init. */ mov __libc_csu_fini@GOTPCREL(%rip), %R8_LP mov __libc_csu_init@GOTPCREL(%rip), %RCX_LP mov main@GOTPCREL(%rip), %RDI_LP -#else +# else /* Pass address of our own entry points to .fini and .init. */ mov $__libc_csu_fini, %R8_LP mov $__libc_csu_init, %RCX_LP mov $main, %RDI_LP -#endif +# endif /* Call the user's main function, and exit with its value. But let the libc call main. Since __libc_start_main in @@ -118,10 +135,12 @@ ENTRY (_start) 2.26 or above can convert indirect branch into direct branch. */ call *__libc_start_main@GOTPCREL(%rip) +#endif hlt /* Crash if somehow `exit' does return. */ -END (_start) +END (START) +#ifndef LIBC_MAIN /* Define a symbol for the first piece of initialized data. */ .data .globl __data_start @@ -129,3 +148,4 @@ __data_start: .long 0 .weak data_start data_start = __data_start +#endif -- 2.26.2