Introduce <gmon-entry.h> to define TEXT_START for csu/gmon-start.c

Message ID 878rx0t8em.fsf@oldenburg.str.redhat.com
State Superseded
Headers
Series Introduce <gmon-entry.h> to define TEXT_START for csu/gmon-start.c |

Checks

Context Check Description
dj/TryBot-apply_patch success Patch applied to master at the time it was sent
dj/TryBot-32bit success Build for i686

Commit Message

Florian Weimer Dec. 4, 2021, 8:36 p.m. UTC
  The generic version uses <entry.h> to obtain the ENTRY_POINT
name and redeclares it as a data symbol, under a different
identifier.  This way, it is no longer necessary to inhibit the
declaration of the entry point as a function.

The previous approach to define __ASSEMBLY__ to suppress the
declaration breaks if headers included by <entry.h> are not
compatible with __ASSEMBLY__.  This happens with rseq integration
because it is necessary to include kernel headers in more places.

Tested on i686-linux-gnu and x86_64-linux-gnu.  Built with
build-many-glibcs.py.

---
 csu/gmon-start.c                                   | 22 ++---------------
 sysdeps/generic/gmon-entry.h                       | 28 ++++++++++++++++++++++
 sysdeps/hppa/{entry.h => gmon-entry.h}             |  9 ++-----
 sysdeps/ia64/entry.h                               | 13 ----------
 sysdeps/ia64/gmon-entry.h                          |  7 ++++++
 .../powerpc/powerpc64/{entry.h => gmon-entry.h}    | 23 +++++++-----------
 6 files changed, 47 insertions(+), 55 deletions(-)
  

Comments

H.J. Lu Dec. 4, 2021, 8:53 p.m. UTC | #1
On Sat, Dec 4, 2021 at 12:36 PM Florian Weimer via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> The generic version uses <entry.h> to obtain the ENTRY_POINT
> name and redeclares it as a data symbol, under a different
> identifier.  This way, it is no longer necessary to inhibit the
> declaration of the entry point as a function.
>
> The previous approach to define __ASSEMBLY__ to suppress the
> declaration breaks if headers included by <entry.h> are not
> compatible with __ASSEMBLY__.  This happens with rseq integration
> because it is necessary to include kernel headers in more places.
>
> Tested on i686-linux-gnu and x86_64-linux-gnu.  Built with
> build-many-glibcs.py.
>
> ---
>  csu/gmon-start.c                                   | 22 ++---------------
>  sysdeps/generic/gmon-entry.h                       | 28 ++++++++++++++++++++++
>  sysdeps/hppa/{entry.h => gmon-entry.h}             |  9 ++-----
>  sysdeps/ia64/entry.h                               | 13 ----------
>  sysdeps/ia64/gmon-entry.h                          |  7 ++++++
>  .../powerpc/powerpc64/{entry.h => gmon-entry.h}    | 23 +++++++-----------
>  6 files changed, 47 insertions(+), 55 deletions(-)
>
> diff --git a/csu/gmon-start.c b/csu/gmon-start.c
> index 344606a676..1e35e2f829 100644
> --- a/csu/gmon-start.c
> +++ b/csu/gmon-start.c
> @@ -38,32 +38,14 @@
>  #include <stdlib.h>
>  #include <unistd.h>
>  #include <elf-initfini.h>
> -#define __ASSEMBLY__
> -#include <entry.h>
> -
> -/* Beginning and end of our code segment. We cannot declare them
> -   as the external functions since we want the addresses of those
> -   labels. Taking the address of a function may have different
> -   meanings on different platforms. */
> -#ifdef ENTRY_POINT_DECL
> -ENTRY_POINT_DECL(extern)
> -#else
> -extern char ENTRY_POINT[];
> -#endif
> -extern char etext[];
> +#include <gmon-entry.h>
>
>  /* Use __executable_start as the lowest address to keep profiling records
>     if it provided by the linker.  */
>  extern const char executable_start[] asm ("__executable_start")
>    __attribute__ ((weak, visibility ("hidden")));
>
> -#ifndef TEXT_START
> -# ifdef ENTRY_POINT_DECL
> -#  define TEXT_START ENTRY_POINT
> -# else
> -#  define TEXT_START &ENTRY_POINT
> -# endif
> -#endif
> +extern char etext[];

Can we drop TEXT_START and always use __executable_start?

commit 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Fri Jul 30 19:07:30 2021 -0700

    Use __executable_start as the lowest address for profiling [BZ #28153]

    Glibc assumes that ENTRY_POINT is the lowest address for which we need
    to keep profiling records and BFD linker uses a linker script to place
    the input sections.

    Starting from GCC 4.6, the main function is placed in .text.startup
    section and starting from binutils 2.22, BFD linker with

    commit add44f8d5c5c05e08b11e033127a744d61c26aee
    Author: Alan Modra <amodra@gmail.com>
    Date:   Thu Nov 25 03:03:02 2010 +0000

                * scripttempl/elf.sc: Group .text.exit, text.startup
and .text.hot
                sections.

    places .text.startup section before .text section, which leave the main
    function out of profiling records.

    Starting from binutils 2.15, linker provides __executable_start to mark
    the lowest address of the executable.  Use __executable_start as the
    lowest address to keep the main function in profiling records. This fixes
    [BZ #28153].

>  #if !ELF_INITFINI
>  /* Instead of defining __gmon_start__ globally in gcrt1.o, we make it
> diff --git a/sysdeps/generic/gmon-entry.h b/sysdeps/generic/gmon-entry.h
> new file mode 100644
> index 0000000000..720b0d3338
> --- /dev/null
> +++ b/sysdeps/generic/gmon-entry.h
> @@ -0,0 +1,28 @@
> +/* Entry point address for csu/gmon-start.c.  Generic version.
> +   Copyright (C) 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
> +   <https://www.gnu.org/licenses/>.  */
> +
> +#include <entry.h>
> +
> +/* Beginning and end of our code segment. We cannot declare them
> +   as the external functions since we want the addresses of those
> +   labels. Taking the address of a function may have different
> +   meanings on different platforms. */
> +#define __TEXT_START0(name) \
> +  ({ extern char _start_as_data[] asm (#name); &_start_as_data[0]; })
> +#define __TEXT_START1(name) __TEXT_START0(name)
> +#define TEXT_START __TEXT_START1(ENTRY_POINT)
> diff --git a/sysdeps/hppa/entry.h b/sysdeps/hppa/gmon-entry.h
> similarity index 52%
> rename from sysdeps/hppa/entry.h
> rename to sysdeps/hppa/gmon-entry.h
> index 5ea5b47448..d59f331889 100644
> --- a/sysdeps/hppa/entry.h
> +++ b/sysdeps/hppa/gmon-entry.h
> @@ -1,13 +1,8 @@
> -#ifndef __ASSEMBLY__
> -extern void _start (void);
> -#endif
> +#include <entry.h>
>
>  /* Lives in libgcc.so and canonicalizes function pointers for comparison.  */
>  extern unsigned int __canonicalize_funcptr_for_compare (unsigned int fptr);
>
>  /* The function's entry point is stored in the first word of the
>     function descriptor (plabel) of _start().  */
> -#define ENTRY_POINT __canonicalize_funcptr_for_compare((unsigned int)_start)
> -
> -/* We have to provide a special declaration.  */
> -#define ENTRY_POINT_DECL(class) class void _start (void);
> +#define TEXT_START __canonicalize_funcptr_for_compare((unsigned int)_start)
> diff --git a/sysdeps/ia64/entry.h b/sysdeps/ia64/entry.h
> deleted file mode 100644
> index e11b49fc53..0000000000
> --- a/sysdeps/ia64/entry.h
> +++ /dev/null
> @@ -1,13 +0,0 @@
> -#include <link.h>
> -#include <dl-fptr.h>
> -
> -#ifndef __ASSEMBLY__
> -extern void _start (void);
> -#endif
> -
> -/* The function's entry point is stored in the first word of the
> -   function descriptor (plabel) of _start().  */
> -#define ENTRY_POINT ELF_PTR_TO_FDESC (_start)->ip
> -
> -/* We have to provide a special declaration.  */
> -#define ENTRY_POINT_DECL(class) class void _start (void);
> diff --git a/sysdeps/ia64/gmon-entry.h b/sysdeps/ia64/gmon-entry.h
> new file mode 100644
> index 0000000000..971da7ebd9
> --- /dev/null
> +++ b/sysdeps/ia64/gmon-entry.h
> @@ -0,0 +1,7 @@
> +#include <entry.h>
> +#include <link.h>
> +#include <dl-fptr.h>
> +
> +/* The function's entry point is stored in the first word of the
> +   function descriptor (plabel) of _start().  */
> +#define TEXT_START ELF_PTR_TO_FDESC (_start)->ip
> diff --git a/sysdeps/powerpc/powerpc64/entry.h b/sysdeps/powerpc/powerpc64/gmon-entry.h
> similarity index 73%
> rename from sysdeps/powerpc/powerpc64/entry.h
> rename to sysdeps/powerpc/powerpc64/gmon-entry.h
> index 99c81cb982..04dbfd1231 100644
> --- a/sysdeps/powerpc/powerpc64/entry.h
> +++ b/sysdeps/powerpc/powerpc64/gmon-entry.h
> @@ -1,5 +1,5 @@
> -/* Finding the entry point and start of text.  PowerPC64 version.
> -   Copyright (C) 2002-2021 Free Software Foundation, Inc.
> +/* Entry point address for csu/gmon-start.c.  powerpc64 version.
> +   Copyright (C) 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
> @@ -16,22 +16,15 @@
>     License along with the GNU C Library; if not, see
>     <https://www.gnu.org/licenses/>.  */
>
> -
> -#ifndef __ASSEMBLY__
> -extern void _start (void);
> -#endif
> -
> -#define ENTRY_POINT _start
> -
> -#if _CALL_ELF != 2
> -/* We have to provide a special declaration.  */
> -#define ENTRY_POINT_DECL(class) class void _start (void);
> -
> +#if _CALL_ELF == 2
> +# include <sysdeps/generic/gmon-entry.h>
> +#else
> +# include <entry.h>
>  /* Use the address of ._start as the lowest address for which we need
>     to keep profiling records.  We can't copy the ia64 scheme as our
>     entry poiny address is really the address of the function
>     descriptor, not the actual function entry.  */
> -#define TEXT_START \
> +# define TEXT_START \
>    ({ extern unsigned long int _start_as_data[] asm ("_start");  \
> -     _start_as_data[0]; })
> +    _start_as_data[0]; })
>  #endif
>
  
Florian Weimer Dec. 4, 2021, 9:13 p.m. UTC | #2
* H. J. Lu:

> Can we drop TEXT_START and always use __executable_start?

Why wasn' this part

> commit 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772
> Author: H.J. Lu <hjl.tools@gmail.com>
> Date:   Fri Jul 30 19:07:30 2021 -0700
>
>     Use __executable_start as the lowest address for profiling [BZ #28153]

of this commit?

I want to make a conservative change here.

Thanks,
Florian
  
H.J. Lu Dec. 4, 2021, 9:40 p.m. UTC | #3
On Sat, Dec 4, 2021 at 1:14 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > Can we drop TEXT_START and always use __executable_start?
>
> Why wasn' this part
>
> > commit 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772
> > Author: H.J. Lu <hjl.tools@gmail.com>
> > Date:   Fri Jul 30 19:07:30 2021 -0700
> >
> >     Use __executable_start as the lowest address for profiling [BZ #28153]
>
> of this commit?
>
> I want to make a conservative change here.
>

Using TEXT_START as the lowest address has been wrong for more than 10
years.  We should drop it now.
  
Florian Weimer Dec. 5, 2021, 7:22 a.m. UTC | #4
* H. J. Lu via Libc-alpha:

> On Sat, Dec 4, 2021 at 1:14 PM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> > Can we drop TEXT_START and always use __executable_start?
>>
>> Why wasn' this part
>>
>> > commit 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772
>> > Author: H.J. Lu <hjl.tools@gmail.com>
>> > Date:   Fri Jul 30 19:07:30 2021 -0700
>> >
>> >     Use __executable_start as the lowest address for profiling [BZ #28153]
>>
>> of this commit?
>>
>> I want to make a conservative change here.
>>
>
> Using TEXT_START as the lowest address has been wrong for more than 10
> years.  We should drop it now.

It seems to work.  I'm going to run a few mor tests.

Thanks,
Florian
  

Patch

diff --git a/csu/gmon-start.c b/csu/gmon-start.c
index 344606a676..1e35e2f829 100644
--- a/csu/gmon-start.c
+++ b/csu/gmon-start.c
@@ -38,32 +38,14 @@ 
 #include <stdlib.h>
 #include <unistd.h>
 #include <elf-initfini.h>
-#define __ASSEMBLY__
-#include <entry.h>
-
-/* Beginning and end of our code segment. We cannot declare them
-   as the external functions since we want the addresses of those
-   labels. Taking the address of a function may have different
-   meanings on different platforms. */
-#ifdef ENTRY_POINT_DECL
-ENTRY_POINT_DECL(extern)
-#else
-extern char ENTRY_POINT[];
-#endif
-extern char etext[];
+#include <gmon-entry.h>
 
 /* Use __executable_start as the lowest address to keep profiling records
    if it provided by the linker.  */
 extern const char executable_start[] asm ("__executable_start")
   __attribute__ ((weak, visibility ("hidden")));
 
-#ifndef TEXT_START
-# ifdef ENTRY_POINT_DECL
-#  define TEXT_START ENTRY_POINT
-# else
-#  define TEXT_START &ENTRY_POINT
-# endif
-#endif
+extern char etext[];
 
 #if !ELF_INITFINI
 /* Instead of defining __gmon_start__ globally in gcrt1.o, we make it
diff --git a/sysdeps/generic/gmon-entry.h b/sysdeps/generic/gmon-entry.h
new file mode 100644
index 0000000000..720b0d3338
--- /dev/null
+++ b/sysdeps/generic/gmon-entry.h
@@ -0,0 +1,28 @@ 
+/* Entry point address for csu/gmon-start.c.  Generic version.
+   Copyright (C) 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
+   <https://www.gnu.org/licenses/>.  */
+
+#include <entry.h>
+
+/* Beginning and end of our code segment. We cannot declare them
+   as the external functions since we want the addresses of those
+   labels. Taking the address of a function may have different
+   meanings on different platforms. */
+#define __TEXT_START0(name) \
+  ({ extern char _start_as_data[] asm (#name); &_start_as_data[0]; })
+#define __TEXT_START1(name) __TEXT_START0(name)
+#define TEXT_START __TEXT_START1(ENTRY_POINT)
diff --git a/sysdeps/hppa/entry.h b/sysdeps/hppa/gmon-entry.h
similarity index 52%
rename from sysdeps/hppa/entry.h
rename to sysdeps/hppa/gmon-entry.h
index 5ea5b47448..d59f331889 100644
--- a/sysdeps/hppa/entry.h
+++ b/sysdeps/hppa/gmon-entry.h
@@ -1,13 +1,8 @@ 
-#ifndef __ASSEMBLY__
-extern void _start (void);
-#endif
+#include <entry.h>
 
 /* Lives in libgcc.so and canonicalizes function pointers for comparison.  */
 extern unsigned int __canonicalize_funcptr_for_compare (unsigned int fptr);
 
 /* The function's entry point is stored in the first word of the
    function descriptor (plabel) of _start().  */
-#define ENTRY_POINT __canonicalize_funcptr_for_compare((unsigned int)_start)
-
-/* We have to provide a special declaration.  */
-#define ENTRY_POINT_DECL(class) class void _start (void);
+#define TEXT_START __canonicalize_funcptr_for_compare((unsigned int)_start)
diff --git a/sysdeps/ia64/entry.h b/sysdeps/ia64/entry.h
deleted file mode 100644
index e11b49fc53..0000000000
--- a/sysdeps/ia64/entry.h
+++ /dev/null
@@ -1,13 +0,0 @@ 
-#include <link.h>
-#include <dl-fptr.h>
-
-#ifndef __ASSEMBLY__
-extern void _start (void);
-#endif
-
-/* The function's entry point is stored in the first word of the
-   function descriptor (plabel) of _start().  */
-#define ENTRY_POINT ELF_PTR_TO_FDESC (_start)->ip
-
-/* We have to provide a special declaration.  */
-#define ENTRY_POINT_DECL(class) class void _start (void);
diff --git a/sysdeps/ia64/gmon-entry.h b/sysdeps/ia64/gmon-entry.h
new file mode 100644
index 0000000000..971da7ebd9
--- /dev/null
+++ b/sysdeps/ia64/gmon-entry.h
@@ -0,0 +1,7 @@ 
+#include <entry.h>
+#include <link.h>
+#include <dl-fptr.h>
+
+/* The function's entry point is stored in the first word of the
+   function descriptor (plabel) of _start().  */
+#define TEXT_START ELF_PTR_TO_FDESC (_start)->ip
diff --git a/sysdeps/powerpc/powerpc64/entry.h b/sysdeps/powerpc/powerpc64/gmon-entry.h
similarity index 73%
rename from sysdeps/powerpc/powerpc64/entry.h
rename to sysdeps/powerpc/powerpc64/gmon-entry.h
index 99c81cb982..04dbfd1231 100644
--- a/sysdeps/powerpc/powerpc64/entry.h
+++ b/sysdeps/powerpc/powerpc64/gmon-entry.h
@@ -1,5 +1,5 @@ 
-/* Finding the entry point and start of text.  PowerPC64 version.
-   Copyright (C) 2002-2021 Free Software Foundation, Inc.
+/* Entry point address for csu/gmon-start.c.  powerpc64 version.
+   Copyright (C) 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
@@ -16,22 +16,15 @@ 
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
-
-#ifndef __ASSEMBLY__
-extern void _start (void);
-#endif
-
-#define ENTRY_POINT _start
-
-#if _CALL_ELF != 2
-/* We have to provide a special declaration.  */
-#define ENTRY_POINT_DECL(class) class void _start (void);
-
+#if _CALL_ELF == 2
+# include <sysdeps/generic/gmon-entry.h>
+#else
+# include <entry.h>
 /* Use the address of ._start as the lowest address for which we need
    to keep profiling records.  We can't copy the ia64 scheme as our
    entry poiny address is really the address of the function
    descriptor, not the actual function entry.  */
-#define TEXT_START \
+# define TEXT_START \
   ({ extern unsigned long int _start_as_data[] asm ("_start");  \
-     _start_as_data[0]; })
+    _start_as_data[0]; })
 #endif