[v2] Place ENTRY_POINT in .text.unlikely section [BZ #28153]

Message ID 20210731151316.1659316-1-hjl.tools@gmail.com
State Superseded
Headers
Series [v2] Place ENTRY_POINT in .text.unlikely section [BZ #28153] |

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

H.J. Lu July 31, 2021, 3:13 p.m. UTC
  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.

Since GCC 4.6, the main function is placed in .text.startup section and
since 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.

Because ENTRY_POINT in gcrt1.o, which is passed to the linker first, is
placed in .text section, linker may place the main function below
ENTRY_POINT, which leaves the main function out of profiling records.

Place ENTRY_POINT in .text.unlikely section so that when GNU binutils
2.20 or newer with

commit 4c4fb5dac57a7cc4704fffb1f2fc11634dccc833
Author: Alan Modra <amodra@gmail.com>
Date:   Fri Sep 4 06:35:29 2009 +0000

            * scripttempl/elf.sc (.text): Add cold text sections.

is used, BFD linker places ENTRY_POINT at the lowest address.  This
fixes [BZ #28153].

Tested on Linux/x86-64, Linux/x32 and Linux/i686 as well as with
build-many-glibcs.py.
---
 gmon/tst-gmon-gprof.sh            | 2 ++
 gmon/tst-gmon-static-gprof.sh     | 2 ++
 sysdeps/aarch64/start.S           | 2 +-
 sysdeps/alpha/start.S             | 2 +-
 sysdeps/arc/start.S               | 1 +
 sysdeps/arm/start.S               | 2 +-
 sysdeps/csky/abiv2/start.S        | 2 +-
 sysdeps/hppa/start.S              | 2 +-
 sysdeps/i386/start.S              | 1 +
 sysdeps/ia64/start.S              | 1 +
 sysdeps/m68k/start.S              | 2 +-
 sysdeps/microblaze/start.S        | 2 +-
 sysdeps/mips/start.S              | 2 +-
 sysdeps/nios2/start.S             | 2 +-
 sysdeps/powerpc/powerpc32/start.S | 2 +-
 sysdeps/powerpc/powerpc64/start.S | 2 +-
 sysdeps/riscv/start.S             | 1 +
 sysdeps/s390/s390-32/start.S      | 2 +-
 sysdeps/s390/s390-64/start.S      | 2 +-
 sysdeps/sh/start.S                | 2 +-
 sysdeps/sparc/sparc32/start.S     | 2 +-
 sysdeps/sparc/sparc64/start.S     | 2 +-
 sysdeps/x86_64/start.S            | 1 +
 23 files changed, 25 insertions(+), 16 deletions(-)
  

Comments

Florian Weimer July 31, 2021, 4:36 p.m. UTC | #1
* H. J. Lu via Libc-alpha:

> diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S
> index 417da8802b..e46e01ed0b 100644
> --- a/sysdeps/aarch64/start.S
> +++ b/sysdeps/aarch64/start.S
> @@ -42,7 +42,7 @@
>  					NULL
>   */
>  
> -	.text
> +	.section .text.unlikely,"ax",%progbits
>  ENTRY(_start)
>  	/* Create an initial frame with 0 LR and FP */
>  	cfi_undefined (x30)

I don't think it's correct to place code that runs during every process
start into .text.unlikely.  Surely we can avoid that page fault.

Can we fix the ENTRY_POINT assumption in profiling instead?

Thanks,
Florian
  
H.J. Lu July 31, 2021, 5:06 p.m. UTC | #2
On Sat, Jul 31, 2021 at 9:36 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu via Libc-alpha:
>
> > diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S
> > index 417da8802b..e46e01ed0b 100644
> > --- a/sysdeps/aarch64/start.S
> > +++ b/sysdeps/aarch64/start.S
> > @@ -42,7 +42,7 @@
> >                                       NULL
> >   */
> >
> > -     .text
> > +     .section .text.unlikely,"ax",%progbits
> >  ENTRY(_start)
> >       /* Create an initial frame with 0 LR and FP */
> >       cfi_undefined (x30)
>
> I don't think it's correct to place code that runs during every process
> start into .text.unlikely.  Surely we can avoid that page fault.
>
> Can we fix the ENTRY_POINT assumption in profiling instead?

We can do

diff --git a/csu/gmon-start.c b/csu/gmon-start.c
index b3432885b3..83322fd586 100644
--- a/csu/gmon-start.c
+++ b/csu/gmon-start.c
@@ -48,7 +48,7 @@
 #ifdef ENTRY_POINT_DECL
 ENTRY_POINT_DECL(extern)
 #else
-extern char ENTRY_POINT[];
+extern char entry_point[] asm (__SYMBOL_PREFIX "main");
 #endif
 extern char etext[];

@@ -56,7 +56,7 @@ extern char etext[];
 # ifdef ENTRY_POINT_DECL
 #  define TEXT_START ENTRY_POINT
 # else
-#  define TEXT_START &ENTRY_POINT
+#  define TEXT_START &entry_point
 # endif
 #endif

But this may only work with BFD linker which places .text.startup
section before .text section.
  
H.J. Lu July 31, 2021, 5:09 p.m. UTC | #3
On Sat, Jul 31, 2021 at 10:06 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sat, Jul 31, 2021 at 9:36 AM Florian Weimer <fweimer@redhat.com> wrote:
> >
> > * H. J. Lu via Libc-alpha:
> >
> > > diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S
> > > index 417da8802b..e46e01ed0b 100644
> > > --- a/sysdeps/aarch64/start.S
> > > +++ b/sysdeps/aarch64/start.S
> > > @@ -42,7 +42,7 @@
> > >                                       NULL
> > >   */
> > >
> > > -     .text
> > > +     .section .text.unlikely,"ax",%progbits
> > >  ENTRY(_start)
> > >       /* Create an initial frame with 0 LR and FP */
> > >       cfi_undefined (x30)
> >
> > I don't think it's correct to place code that runs during every process
> > start into .text.unlikely.  Surely we can avoid that page fault.
> >
> > Can we fix the ENTRY_POINT assumption in profiling instead?
>
> We can do
>
> diff --git a/csu/gmon-start.c b/csu/gmon-start.c
> index b3432885b3..83322fd586 100644
> --- a/csu/gmon-start.c
> +++ b/csu/gmon-start.c
> @@ -48,7 +48,7 @@
>  #ifdef ENTRY_POINT_DECL
>  ENTRY_POINT_DECL(extern)
>  #else
> -extern char ENTRY_POINT[];
> +extern char entry_point[] asm (__SYMBOL_PREFIX "main");
>  #endif
>  extern char etext[];
>
> @@ -56,7 +56,7 @@ extern char etext[];
>  # ifdef ENTRY_POINT_DECL
>  #  define TEXT_START ENTRY_POINT
>  # else
> -#  define TEXT_START &ENTRY_POINT
> +#  define TEXT_START &entry_point
>  # endif
>  #endif
>
> But this may only work with BFD linker which places .text.startup
> section before .text section.

Another option is to place _start in .text.startup which leaves

    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)

sections out of profiling records.
  
Florian Weimer July 31, 2021, 5:11 p.m. UTC | #4
* H. J. Lu:

> On Sat, Jul 31, 2021 at 9:36 AM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu via Libc-alpha:
>>
>> > diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S
>> > index 417da8802b..e46e01ed0b 100644
>> > --- a/sysdeps/aarch64/start.S
>> > +++ b/sysdeps/aarch64/start.S
>> > @@ -42,7 +42,7 @@
>> >                                       NULL
>> >   */
>> >
>> > -     .text
>> > +     .section .text.unlikely,"ax",%progbits
>> >  ENTRY(_start)
>> >       /* Create an initial frame with 0 LR and FP */
>> >       cfi_undefined (x30)
>>
>> I don't think it's correct to place code that runs during every process
>> start into .text.unlikely.  Surely we can avoid that page fault.
>>
>> Can we fix the ENTRY_POINT assumption in profiling instead?
>
> We can do
>
> diff --git a/csu/gmon-start.c b/csu/gmon-start.c
> index b3432885b3..83322fd586 100644
> --- a/csu/gmon-start.c
> +++ b/csu/gmon-start.c
> @@ -48,7 +48,7 @@
>  #ifdef ENTRY_POINT_DECL
>  ENTRY_POINT_DECL(extern)
>  #else
> -extern char ENTRY_POINT[];
> +extern char entry_point[] asm (__SYMBOL_PREFIX "main");
>  #endif
>  extern char etext[];
>
> @@ -56,7 +56,7 @@ extern char etext[];
>  # ifdef ENTRY_POINT_DECL
>  #  define TEXT_START ENTRY_POINT
>  # else
> -#  define TEXT_START &ENTRY_POINT
> +#  define TEXT_START &entry_point
>  # endif
>  #endif
>
> But this may only work with BFD linker which places .text.startup
> section before .text section.

Can we get the linker to emit a symbol at the start of the text section?
Like it does for orphan sections?

Then we can use a weak symbol reference in gmon-start.c and use the new
symbol if it is available.

Thanks,
Florian
  
Andreas Schwab July 31, 2021, 5:34 p.m. UTC | #5
On Jul 31 2021, Florian Weimer via Libc-alpha wrote:

> Can we get the linker to emit a symbol at the start of the text section?

There is __executable_start at the start of the text segment.

Andreas.
  
H.J. Lu July 31, 2021, 5:43 p.m. UTC | #6
On Sat, Jul 31, 2021 at 10:11 AM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > On Sat, Jul 31, 2021 at 9:36 AM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * H. J. Lu via Libc-alpha:
> >>
> >> > diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S
> >> > index 417da8802b..e46e01ed0b 100644
> >> > --- a/sysdeps/aarch64/start.S
> >> > +++ b/sysdeps/aarch64/start.S
> >> > @@ -42,7 +42,7 @@
> >> >                                       NULL
> >> >   */
> >> >
> >> > -     .text
> >> > +     .section .text.unlikely,"ax",%progbits
> >> >  ENTRY(_start)
> >> >       /* Create an initial frame with 0 LR and FP */
> >> >       cfi_undefined (x30)
> >>
> >> I don't think it's correct to place code that runs during every process
> >> start into .text.unlikely.  Surely we can avoid that page fault.
> >>
> >> Can we fix the ENTRY_POINT assumption in profiling instead?
> >
> > We can do
> >
> > diff --git a/csu/gmon-start.c b/csu/gmon-start.c
> > index b3432885b3..83322fd586 100644
> > --- a/csu/gmon-start.c
> > +++ b/csu/gmon-start.c
> > @@ -48,7 +48,7 @@
> >  #ifdef ENTRY_POINT_DECL
> >  ENTRY_POINT_DECL(extern)
> >  #else
> > -extern char ENTRY_POINT[];
> > +extern char entry_point[] asm (__SYMBOL_PREFIX "main");
> >  #endif
> >  extern char etext[];
> >
> > @@ -56,7 +56,7 @@ extern char etext[];
> >  # ifdef ENTRY_POINT_DECL
> >  #  define TEXT_START ENTRY_POINT
> >  # else
> > -#  define TEXT_START &ENTRY_POINT
> > +#  define TEXT_START &entry_point
> >  # endif
> >  #endif
> >
> > But this may only work with BFD linker which places .text.startup
> > section before .text section.
>
> Can we get the linker to emit a symbol at the start of the text section?

We already have __executable_start which is pretty close to what we
need.   Like this.

> Like it does for orphan sections?
>
> Then we can use a weak symbol reference in gmon-start.c and use the new
> symbol if it is available.
>
> Thanks,
> Florian
>
  

Patch

diff --git a/gmon/tst-gmon-gprof.sh b/gmon/tst-gmon-gprof.sh
index 9d371582b9..dc0be02110 100644
--- a/gmon/tst-gmon-gprof.sh
+++ b/gmon/tst-gmon-gprof.sh
@@ -39,12 +39,14 @@  trap cleanup 0
 cat > "$expected" <<EOF
 f1 2000
 f2 1000
+f3 1
 EOF
 
 # Special version for powerpc with function descriptors.
 cat > "$expected_dot" <<EOF
 .f1 2000
 .f2 1000
+.f3 1
 EOF
 
 "$GPROF" -C "$program" "$data" \
diff --git a/gmon/tst-gmon-static-gprof.sh b/gmon/tst-gmon-static-gprof.sh
index 79218df967..4cc99c80d0 100644
--- a/gmon/tst-gmon-static-gprof.sh
+++ b/gmon/tst-gmon-static-gprof.sh
@@ -39,6 +39,7 @@  trap cleanup 0
 cat > "$expected" <<EOF
 f1 2000
 f2 1000
+f3 1
 main 1
 EOF
 
@@ -46,6 +47,7 @@  EOF
 cat > "$expected_dot" <<EOF
 .f1 2000
 .f2 1000
+.f3 1
 .main 1
 EOF
 
diff --git a/sysdeps/aarch64/start.S b/sysdeps/aarch64/start.S
index 417da8802b..e46e01ed0b 100644
--- a/sysdeps/aarch64/start.S
+++ b/sysdeps/aarch64/start.S
@@ -42,7 +42,7 @@ 
 					NULL
  */
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 ENTRY(_start)
 	/* Create an initial frame with 0 LR and FP */
 	cfi_undefined (x30)
diff --git a/sysdeps/alpha/start.S b/sysdeps/alpha/start.S
index 65dcd4d392..6658a39813 100644
--- a/sysdeps/alpha/start.S
+++ b/sysdeps/alpha/start.S
@@ -36,7 +36,7 @@ 
 
 #include <sysdep.h>
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.align 3
 	.globl _start
 	.ent _start, 0
diff --git a/sysdeps/arc/start.S b/sysdeps/arc/start.S
index 5302a57cab..aca293faf9 100644
--- a/sysdeps/arc/start.S
+++ b/sysdeps/arc/start.S
@@ -33,6 +33,7 @@ 
         env[0...N]      environment variables (pointers)
         NULL.  */
 
+	.section .text.unlikely,"ax",%progbits
 ENTRY (ENTRY_POINT)
 
 	/* Needed to make gdb backtraces stop here.  */
diff --git a/sysdeps/arm/start.S b/sysdeps/arm/start.S
index 9b56bc0cca..4b0b098bb6 100644
--- a/sysdeps/arm/start.S
+++ b/sysdeps/arm/start.S
@@ -69,7 +69,7 @@ 
 	.syntax unified
 #endif
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl _start
 	.type _start,#function
 _start:
diff --git a/sysdeps/csky/abiv2/start.S b/sysdeps/csky/abiv2/start.S
index a565cfa87b..1061da75da 100644
--- a/sysdeps/csky/abiv2/start.S
+++ b/sysdeps/csky/abiv2/start.S
@@ -41,7 +41,7 @@ 
 
 #include <sysdep.h>
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl _start;
 	.type _start,@function;
 	.align 4;
diff --git a/sysdeps/hppa/start.S b/sysdeps/hppa/start.S
index 4a1877f8e8..f1164aa030 100644
--- a/sysdeps/hppa/start.S
+++ b/sysdeps/hppa/start.S
@@ -51,7 +51,7 @@ 
 .Lp__libc_start_main:
 	.word P%__libc_start_main
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.align 4
 	.globl _start
 	.export _start, ENTRY
diff --git a/sysdeps/i386/start.S b/sysdeps/i386/start.S
index 5296b27e65..ee97f22a27 100644
--- a/sysdeps/i386/start.S
+++ b/sysdeps/i386/start.S
@@ -54,6 +54,7 @@ 
 
 #include <sysdep.h>
 
+	.section .text.unlikely,"ax",%progbits
 ENTRY (_start)
 	/* Clearing frame pointer is insufficient, use CFI.  */
 	cfi_undefined (eip)
diff --git a/sysdeps/ia64/start.S b/sysdeps/ia64/start.S
index b28f8cb429..6079e67345 100644
--- a/sysdeps/ia64/start.S
+++ b/sysdeps/ia64/start.S
@@ -48,6 +48,7 @@ 
  *	out6:	stack_end
  */
 
+	.section .text.unlikely,"ax",%progbits
 	.align 32
 	.global _start
 
diff --git a/sysdeps/m68k/start.S b/sysdeps/m68k/start.S
index 98da4db9f3..a2bdac5c44 100644
--- a/sysdeps/m68k/start.S
+++ b/sysdeps/m68k/start.S
@@ -54,7 +54,7 @@ 
 
 #include <sysdep.h>
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl _start
 	.type _start,@function
 _start:
diff --git a/sysdeps/microblaze/start.S b/sysdeps/microblaze/start.S
index 6589bd4dc7..9db90bf4bd 100644
--- a/sysdeps/microblaze/start.S
+++ b/sysdeps/microblaze/start.S
@@ -33,7 +33,7 @@ 
    License along with the GNU C Library.  If not, see
    <https://www.gnu.org/licenses/>.  */
 
-    .text
+	.section .text.unlikely,"ax",%progbits
     .globl _start
     .type _start,@function
 _start:
diff --git a/sysdeps/mips/start.S b/sysdeps/mips/start.S
index 4ec42a2a7f..c29b87d32f 100644
--- a/sysdeps/mips/start.S
+++ b/sysdeps/mips/start.S
@@ -71,7 +71,7 @@ 
 		      void (*rtld_fini) (void), void *stack_end)
 */
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl ENTRY_POINT
 	.type ENTRY_POINT,@function
 #ifndef __mips16
diff --git a/sysdeps/nios2/start.S b/sysdeps/nios2/start.S
index 7c9696977f..c963c37476 100644
--- a/sysdeps/nios2/start.S
+++ b/sysdeps/nios2/start.S
@@ -65,7 +65,7 @@ 
 	value, terminated by an AT_NULL tag.
 */
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl _start
 	.type _start,%function
 _start:
diff --git a/sysdeps/powerpc/powerpc32/start.S b/sysdeps/powerpc/powerpc32/start.S
index 39ce1a18ff..1ed3669c07 100644
--- a/sysdeps/powerpc/powerpc32/start.S
+++ b/sysdeps/powerpc/powerpc32/start.S
@@ -56,7 +56,7 @@  L(start_addresses):
 	.long 	0 /* Used to be fini.  */
 	ASM_SIZE_DIRECTIVE(L(start_addresses))
 
-	.section ".text"
+	.section .text.unlikely,"ax",%progbits
 ENTRY(_start)
  /* Save the stack pointer, in case we're statically linked under Linux.  */
 	mr	r9,r1
diff --git a/sysdeps/powerpc/powerpc64/start.S b/sysdeps/powerpc/powerpc64/start.S
index 71c0c67926..f1597164c4 100644
--- a/sysdeps/powerpc/powerpc64/start.S
+++ b/sysdeps/powerpc/powerpc64/start.S
@@ -61,7 +61,7 @@  L(start_addresses):
 	.section	".toc","aw"
 .L01:
 	.tc	L(start_addresses)[TC],L(start_addresses)
-	.section ".text"
+	.section .text.unlikely,"ax",%progbits
 ENTRY (_start)
  /* Save the stack pointer, in case we're statically linked under Linux.  */
 	mr	r9,r1
diff --git a/sysdeps/riscv/start.S b/sysdeps/riscv/start.S
index 806f6aacd6..64b8c2699c 100644
--- a/sysdeps/riscv/start.S
+++ b/sysdeps/riscv/start.S
@@ -42,6 +42,7 @@ 
    a0 contains the address of a function to be passed to atexit.
    __libc_start_main wants this in a5.  */
 
+	.section .text.unlikely,"ax",%progbits
 ENTRY (ENTRY_POINT)
 	/* Terminate call stack by noting ra is undefined.  Use a dummy
 	   .cfi_label to force starting the FDE.  */
diff --git a/sysdeps/s390/s390-32/start.S b/sysdeps/s390/s390-32/start.S
index b6cfa4caf3..734c32505f 100644
--- a/sysdeps/s390/s390-32/start.S
+++ b/sysdeps/s390/s390-32/start.S
@@ -55,7 +55,7 @@ 
 					NULL
 */
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl _start
 	.type _start,@function
 _start:
diff --git a/sysdeps/s390/s390-64/start.S b/sysdeps/s390/s390-64/start.S
index 4e6526308a..473576a456 100644
--- a/sysdeps/s390/s390-64/start.S
+++ b/sysdeps/s390/s390-64/start.S
@@ -55,7 +55,7 @@ 
 					NULL
 */
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl _start
 	.type _start,@function
 _start:
diff --git a/sysdeps/sh/start.S b/sysdeps/sh/start.S
index 606ee59222..f929b5d51b 100644
--- a/sysdeps/sh/start.S
+++ b/sysdeps/sh/start.S
@@ -57,7 +57,7 @@ 
 					NULL
 */
 
-	.text
+	.section .text.unlikely,"ax",%progbits
 	.globl _start
 	.type _start,@function
 _start:
diff --git a/sysdeps/sparc/sparc32/start.S b/sysdeps/sparc/sparc32/start.S
index 00bf898fb9..2f6467832f 100644
--- a/sysdeps/sparc/sparc32/start.S
+++ b/sysdeps/sparc/sparc32/start.S
@@ -37,7 +37,7 @@ 
 #include <sysdep.h>
 
 
-	.section ".text"
+	.section .text.unlikely,"ax",%progbits
 	.align 4
 	.global _start
 	.type _start,#function
diff --git a/sysdeps/sparc/sparc64/start.S b/sysdeps/sparc/sparc64/start.S
index 8520717eba..9f7e94d719 100644
--- a/sysdeps/sparc/sparc64/start.S
+++ b/sysdeps/sparc/sparc64/start.S
@@ -37,7 +37,7 @@ 
 #include <sysdep.h>
 
 
-	.section ".text"
+	.section .text.unlikely,"ax",%progbits
 	.align 4
 	.global _start
 	.type _start,#function
diff --git a/sysdeps/x86_64/start.S b/sysdeps/x86_64/start.S
index 1b3e36826b..5f61764093 100644
--- a/sysdeps/x86_64/start.S
+++ b/sysdeps/x86_64/start.S
@@ -55,6 +55,7 @@ 
 
 #include <sysdep.h>
 
+	.section .text.unlikely,"ax",%progbits
 ENTRY (_start)
 	/* Clearing frame pointer is insufficient, use CFI.  */
 	cfi_undefined (rip)